{", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST},
{", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET},
{", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA},
- {", HelloRetryRequest", SSL3_MT_HELLO_RETRY_REQUEST},
{", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS},
{", Certificate", SSL3_MT_CERTIFICATE},
{", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE},
SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE:384:\
tls_post_process_client_key_exchange
SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE:360:tls_prepare_client_certificate
+SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST:610:tls_process_as_hello_retry_request
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST:361:tls_process_certificate_request
SSL_F_TLS_PROCESS_CERT_STATUS:362:*
SSL_F_TLS_PROCESS_CERT_STATUS_BODY:495:tls_process_cert_status_body
TLS_ST_CR_CERT_VRFY,
TLS_ST_SW_CERT_VRFY,
TLS_ST_CR_HELLO_REQ,
- TLS_ST_SW_HELLO_RETRY_REQUEST,
- TLS_ST_CR_HELLO_RETRY_REQUEST,
TLS_ST_SW_KEY_UPDATE,
TLS_ST_CW_KEY_UPDATE,
TLS_ST_SR_KEY_UPDATE,
# define SSL3_MT_SERVER_HELLO 2
# define SSL3_MT_NEWSESSION_TICKET 4
# define SSL3_MT_END_OF_EARLY_DATA 5
-# define SSL3_MT_HELLO_RETRY_REQUEST 6
# define SSL3_MT_ENCRYPTED_EXTENSIONS 8
# define SSL3_MT_CERTIFICATE 11
# define SSL3_MT_SERVER_KEY_EXCHANGE 12
# define SSL_F_TLS_POST_PROCESS_CLIENT_HELLO 378
# define SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE 384
# define SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE 360
+# define SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST 610
# define SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST 361
# define SSL_F_TLS_PROCESS_CERT_STATUS 362
# define SSL_F_TLS_PROCESS_CERT_STATUS_BODY 495
"tls_post_process_client_key_exchange"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE, 0),
"tls_prepare_client_certificate"},
+ {ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST, 0),
+ "tls_process_as_hello_retry_request"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST, 0),
"tls_process_certificate_request"},
{ERR_PACK(ERR_LIB_SSL, SSL_F_TLS_PROCESS_CERT_STATUS, 0), ""},
return "TLSv1.3 write server certificate verify";
case TLS_ST_CR_HELLO_REQ:
return "SSLv3/TLS read hello request";
- case TLS_ST_SW_HELLO_RETRY_REQUEST:
- return "TLSv1.3 write hello retry request";
- case TLS_ST_CR_HELLO_RETRY_REQUEST:
- return "TLSv1.3 read hello retry request";
case TLS_ST_SW_KEY_UPDATE:
return "TLSv1.3 write server key update";
case TLS_ST_CW_KEY_UPDATE:
return "TRSCV";
case TLS_ST_CR_HELLO_REQ:
return "TRHR";
- case TLS_ST_SW_HELLO_RETRY_REQUEST:
- return "TWHRR";
- case TLS_ST_CR_HELLO_RETRY_REQUEST:
- return "TRHRR";
case TLS_ST_SW_KEY_UPDATE:
return "TWSKU";
case TLS_ST_CW_KEY_UPDATE:
#include <openssl/bn.h>
#include <openssl/engine.h>
-static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt);
+static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
static ossl_inline int cert_req_allowed(SSL *s);
st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
return 1;
}
- } else {
- if (mt == SSL3_MT_HELLO_RETRY_REQUEST) {
- st->hand_state = TLS_ST_CR_HELLO_RETRY_REQUEST;
- return 1;
- }
}
break;
st->hand_state = TLS_ST_CR_SRVR_HELLO;
return 1;
}
- if (mt == SSL3_MT_HELLO_RETRY_REQUEST) {
- st->hand_state = TLS_ST_CR_HELLO_RETRY_REQUEST;
- return 1;
- }
break;
case TLS_ST_CR_SRVR_HELLO:
*/
return WRITE_TRAN_FINISHED;
- case TLS_ST_CR_HELLO_RETRY_REQUEST:
+ case TLS_ST_CR_SRVR_HELLO:
+ /* We only get here in TLSv1.3 */
st->hand_state = TLS_ST_CW_CLNT_HELLO;
return WRITE_TRAN_CONTINUE;
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return HELLO_VERIFY_REQUEST_MAX_LENGTH;
- case TLS_ST_CR_HELLO_RETRY_REQUEST:
- return HELLO_RETRY_REQUEST_MAX_LENGTH;
-
case TLS_ST_CR_CERT:
return s->max_cert_list;
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return dtls_process_hello_verify(s, pkt);
- case TLS_ST_CR_HELLO_RETRY_REQUEST:
- return tls_process_hello_retry_request(s, pkt);
-
case TLS_ST_CR_CERT:
return tls_process_server_certificate(s, pkt);
PACKET session_id, extpkt;
size_t session_id_len;
const unsigned char *cipherchars;
+ int hrr = 0;
unsigned int compression;
unsigned int sversion;
unsigned int context;
}
/* load the server random */
- if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_LENGTH_MISMATCH);
- goto err;
+ if (s->version == TLS1_3_VERSION
+ && sversion == TLS1_2_VERSION
+ && PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE
+ && memcmp(hrrrandom, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) {
+ s->hello_retry_request = hrr = 1;
+ if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
+ } else {
+ if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_LENGTH_MISMATCH);
+ goto err;
+ }
}
/* Get the session-id. */
}
/* TLS extensions */
- if (PACKET_remaining(pkt) == 0) {
+ if (PACKET_remaining(pkt) == 0 && !hrr) {
PACKET_null_init(&extpkt);
} else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|| PACKET_remaining(pkt) != 0) {
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 (!hrr) {
+ 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;
+ }
}
- if (!ssl_choose_client_version(s, sversion, extensions)) {
- /* SSLfatal() already called */
- goto err;
+ if (SSL_IS_TLS13(s) || hrr) {
+ if (compression != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_HELLO,
+ SSL_R_INVALID_COMPRESSION_ALGORITHM);
+ goto err;
+ }
+
+ if (session_id_len != s->tmp_session_id_len
+ || memcmp(PACKET_data(&session_id), s->tmp_session_id,
+ session_id_len) != 0) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
+ goto err;
+ }
+ }
+
+ if (hrr) {
+ if (!set_client_ciphersuite(s, cipherchars)) {
+ /* SSLfatal() already called */
+ goto err;
+ }
+
+ return tls_process_as_hello_retry_request(s, &extpkt);
}
/*
goto err;
}
- if (compression != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO,
- SSL_R_INVALID_COMPRESSION_ALGORITHM);
- goto err;
- }
-
- if (session_id_len != s->tmp_session_id_len
- || memcmp(PACKET_data(&session_id), s->tmp_session_id,
- session_id_len) != 0) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
- goto err;
- }
-
/* This will set s->hit if we are resuming */
if (!tls_parse_extension(s, TLSEXT_IDX_psk,
SSL_EXT_TLS1_3_SERVER_HELLO,
return MSG_PROCESS_ERROR;
}
-static MSG_PROCESS_RETURN tls_process_hello_retry_request(SSL *s, PACKET *pkt)
+static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s,
+ PACKET *extpkt)
{
- unsigned int sversion;
- const unsigned char *cipherchars;
RAW_EXTENSION *extensions = NULL;
- PACKET extpkt;
-
- if (!PACKET_get_net_2(pkt, &sversion)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- /* TODO(TLS1.3): Remove the TLS1_3_VERSION_DRAFT clause before release */
- if (sversion != TLS1_3_VERSION && sversion != TLS1_3_VERSION_DRAFT) {
- SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
- SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
- SSL_R_WRONG_SSL_VERSION);
- goto err;
- }
-
- s->hello_retry_request = 1;
/*
* If we were sending early_data then the enc_write_ctx is now invalid and
EVP_CIPHER_CTX_free(s->enc_write_ctx);
s->enc_write_ctx = NULL;
- if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
- SSL_R_LENGTH_MISMATCH);
- goto err;
- }
-
- if (!set_client_ciphersuite(s, cipherchars)) {
- /* SSLfatal() already called */
- goto err;
- }
-
- if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
- /* Must have a non-empty extensions block */
- || PACKET_remaining(&extpkt) == 0
- /* Must be no trailing data after extensions */
- || PACKET_remaining(pkt) != 0) {
- SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
- SSL_R_BAD_LENGTH);
- goto err;
- }
-
- if (!tls_collect_extensions(s, &extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
+ if (!tls_collect_extensions(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
&extensions, NULL, 1)
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
extensions, NULL, 0, 1)) {
* ClientHello will not change
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
- SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST,
- SSL_R_NO_CHANGE_FOLLOWING_HRR);
+ SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST,
+ SSL_R_NO_CHANGE_FOLLOWING_HRR);
goto err;
}
#include <openssl/evp.h>
#include <openssl/x509.h>
+/* Fixed value used in the ServerHello random field to identify an HRR */
+const unsigned char hrrrandom[] = {
+ 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11, 0xbe, 0x1d, 0x8c, 0x02,
+ 0x1e, 0x65, 0xb8, 0x91, 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
+ 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c
+};
+
/*
* send s->init_buf in records of type 'type' (SSL3_RT_HANDSHAKE or
* SSL3_RT_CHANGE_CIPHER_SPEC)
* We defer feeding in the HRR until later. We'll do it as part of
* processing the message
*/
- if (s->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST
- && !ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
- s->init_num + SSL3_HM_HEADER_LENGTH)) {
- /* SSLfatal() already called */
- *len = 0;
- return 0;
+#define SERVER_HELLO_RANDOM_OFFSET (SSL3_HM_HEADER_LENGTH + 2)
+ if (s->s3->tmp.message_type != SSL3_MT_SERVER_HELLO
+ || s->init_num < SERVER_HELLO_RANDOM_OFFSET + SSL3_RANDOM_SIZE
+ || memcmp(hrrrandom,
+ s->init_buf->data + SERVER_HELLO_RANDOM_OFFSET,
+ SSL3_RANDOM_SIZE) != 0) {
+ if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
+ s->init_num + SSL3_HM_HEADER_LENGTH)) {
+ /* SSLfatal() already called */
+ *len = 0;
+ return 0;
+ }
}
if (s->msg_callback)
s->msg_callback(0, s->version, SSL3_RT_HANDSHAKE, s->init_buf->data,
/* Dummy message type */
#define SSL3_MT_DUMMY -1
+extern const unsigned char hrrrandom[];
+
/* Message processing return codes */
typedef enum {
/* Something bad happened */
#include <openssl/md5.h>
static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt);
-static int tls_construct_hello_retry_request(SSL *s, WPACKET *pkt);
/*
* ossl_statem_server13_read_transition() encapsulates the logic for the allowed
return WRITE_TRAN_FINISHED;
case TLS_ST_SR_CLNT_HELLO:
- if (s->hello_retry_request)
- st->hand_state = TLS_ST_SW_HELLO_RETRY_REQUEST;
- else
- st->hand_state = TLS_ST_SW_SRVR_HELLO;
- return WRITE_TRAN_CONTINUE;
-
- case TLS_ST_SW_HELLO_RETRY_REQUEST:
- st->hand_state = TLS_ST_EARLY_DATA;
+ st->hand_state = TLS_ST_SW_SRVR_HELLO;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SRVR_HELLO:
- if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
+ if (s->hello_retry_request)
+ st->hand_state = TLS_ST_EARLY_DATA;
+ else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
st->hand_state = TLS_ST_SW_CHANGE;
else
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
/* No post work to be done */
break;
- case TLS_ST_SW_HELLO_RETRY_REQUEST:
- if (statem_flush(s) != 1)
- return WORK_MORE_A;
- break;
-
case TLS_ST_SW_HELLO_REQ:
if (statem_flush(s) != 1)
return WORK_MORE_A;
break;
case TLS_ST_SW_SRVR_HELLO:
+ if (SSL_IS_TLS13(s) && s->hello_retry_request) {
+ if (statem_flush(s) != 1)
+ return WORK_MORE_A;
+ break;
+ }
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && s->hit) {
unsigned char sctpauthkey[64];
*mt = SSL3_MT_ENCRYPTED_EXTENSIONS;
break;
- case TLS_ST_SW_HELLO_RETRY_REQUEST:
- *confunc = tls_construct_hello_retry_request;
- *mt = SSL3_MT_HELLO_RETRY_REQUEST;
- break;
-
case TLS_ST_SW_KEY_UPDATE:
*confunc = tls_construct_key_update;
*mt = SSL3_MT_KEY_UPDATE;
size_t sl, len;
int version;
unsigned char *session_id;
+ int usetls13 = SSL_IS_TLS13(s) || s->hello_retry_request;
- version = SSL_IS_TLS13(s) ? TLS1_2_VERSION : s->version;
+ version = usetls13 ? TLS1_2_VERSION : s->version;
if (!WPACKET_put_bytes_u16(pkt, version)
/*
* Random stuff. Filling of the server_random takes place in
* tls_process_client_hello()
*/
- || !WPACKET_memcpy(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
+ || !WPACKET_memcpy(pkt,
+ s->hello_retry_request
+ ? hrrrandom : s->s3->server_random,
+ SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
&& !s->hit))
s->session->session_id_length = 0;
- if (SSL_IS_TLS13(s)) {
+ if (usetls13) {
sl = s->tmp_session_id_len;
session_id = s->tmp_session_id;
} else {
#ifdef OPENSSL_NO_COMP
compm = 0;
#else
- if (SSL_IS_TLS13(s) || s->s3->tmp.new_compression == NULL)
+ if (usetls13 || s->s3->tmp.new_compression == NULL)
compm = 0;
else
compm = s->s3->tmp.new_compression->id;
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
|| !WPACKET_put_bytes_u8(pkt, compm)
|| !tls_construct_extensions(s, pkt,
- SSL_IS_TLS13(s)
- ? SSL_EXT_TLS1_3_SERVER_HELLO
- : SSL_EXT_TLS1_2_SERVER_HELLO,
+ s->hello_retry_request
+ ? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
+ : (SSL_IS_TLS13(s)
+ ? SSL_EXT_TLS1_3_SERVER_HELLO
+ : SSL_EXT_TLS1_2_SERVER_HELLO),
NULL, 0)) {
/* SSLfatal() already called */
return 0;
}
- if (!(s->verify_mode & SSL_VERIFY_PEER)
- && !ssl3_digest_cached_records(s, 0)) {
+ if (s->hello_retry_request) {
+ /* Ditch the session. We'll create a new one next time around */
+ SSL_SESSION_free(s->session);
+ s->session = NULL;
+ s->hit = 0;
+
+ /*
+ * Re-initialise the Transcript Hash. We're going to prepopulate it with
+ * a synthetic message_hash in place of ClientHello1.
+ */
+ if (!create_synthetic_message_hash(s)) {
+ /* SSLfatal() already called */
+ return 0;
+ }
+ } else if (!(s->verify_mode & SSL_VERIFY_PEER)
+ && !ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */;
return 0;
}
return 1;
}
-static int tls_construct_hello_retry_request(SSL *s, WPACKET *pkt)
-{
- size_t len = 0;
-
- /*
- * TODO(TLS1.3): Remove the DRAFT version before release
- * (should be s->version)
- */
- if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)
- || !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt,
- &len)) {
- SSLfatal(s, SSL_AD_INTERNAL_ERROR,
- SSL_F_TLS_CONSTRUCT_HELLO_RETRY_REQUEST, ERR_R_INTERNAL_ERROR);
- return 0;
- }
-
- if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
- NULL, 0)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- /* Ditch the session. We'll create a new one next time around */
- SSL_SESSION_free(s->session);
- s->session = NULL;
- s->hit = 0;
-
- /*
- * Re-initialise the Transcript Hash. We're going to prepopulate it with
- * a synthetic message_hash in place of ClientHello1.
- */
- if (!create_synthetic_message_hash(s)) {
- /* SSLfatal() already called */
- return 0;
- }
-
- return 1;
-}
-
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) != 0) {
{DTLS1_MT_HELLO_VERIFY_REQUEST, "HelloVerifyRequest"},
{SSL3_MT_NEWSESSION_TICKET, "NewSessionTicket"},
{SSL3_MT_END_OF_EARLY_DATA, "EndOfEarlyData"},
- {SSL3_MT_HELLO_RETRY_REQUEST, "HelloRetryRequest"},
{SSL3_MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions"},
{SSL3_MT_CERTIFICATE, "Certificate"},
{SSL3_MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange"},
break;
case TLSEXT_TYPE_key_share:
- if (mt == SSL3_MT_HELLO_RETRY_REQUEST) {
+ if (server && extlen == 2) {
int group_id;
- if (extlen != 2)
- return 0;
+ /* We assume this is an HRR, otherwise this is an invalid key_share */
group_id = (ext[0] << 8) | ext[1];
BIO_indent(bio, indent + 4, 80);
BIO_printf(bio, "NamedGroup: %s (%d)\n",
return 1;
}
-static int ssl_print_hello_retry_request(BIO *bio, int indent,
- const unsigned char *msg,
- size_t msglen)
-{
- unsigned int cs;
-
- if (!ssl_print_version(bio, indent, "server_version", &msg, &msglen, NULL))
- return 0;
-
- cs = (msg[0] << 8) | msg[1];
- BIO_indent(bio, indent, 80);
- BIO_printf(bio, "cipher_suite {0x%02X, 0x%02X} %s\n",
- msg[0], msg[1], ssl_trace_str(cs, ssl_ciphers_tbl));
- msg += 2;
- msglen -= 2;
-
- if (!ssl_print_extensions(bio, indent, 1, SSL3_MT_HELLO_RETRY_REQUEST, &msg,
- &msglen))
- return 0;
-
- return 1;
-}
-
static int ssl_get_keyex(const char **pname, const SSL *ssl)
{
unsigned long alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
return 0;
break;
- case SSL3_MT_HELLO_RETRY_REQUEST:
- if (!ssl_print_hello_retry_request(bio, indent + 2, msg, msglen))
- return 0;
- break;
-
case SSL3_MT_ENCRYPTED_EXTENSIONS:
if (!ssl_print_extensions(bio, indent + 2, 1,
SSL3_MT_ENCRYPTED_EXTENSIONS, &msg, &msglen))
#Test 22: The server sending an HRR but not requesting a new key_share should
# fail
$proxy->clear();
+$direction = SERVER_TO_CLIENT;
$testtype = NO_KEY_SHARES_IN_HRR;
$proxy->serverflags("-curves X25519");
$proxy->start();
if ($testtype == LOOK_ONLY) {
return;
}
+ if ($testtype == NO_KEY_SHARES_IN_HRR) {
+ $message->delete_extension(TLSProxy::Message::EXT_KEY_SHARE);
+ $message->set_extension(TLSProxy::Message::EXT_UNKNOWN, "");
+ $message->repack();
+ return;
+ }
if ($testtype == SELECT_X25519) {
$ext = pack "C4H64",
0x00, 0x1d, #x25519
$message->set_extension(TLSProxy::Message::EXT_KEY_SHARE, $ext);
$message->repack();
- } elsif ($message->mt == TLSProxy::Message::MT_HELLO_RETRY_REQUEST
- && $testtype == NO_KEY_SHARES_IN_HRR) {
- $message->delete_extension(TLSProxy::Message::EXT_KEY_SHARE);
- $message->set_extension(TLSProxy::Message::EXT_UNKNOWN, "");
- $message->repack();
- }
+ }
}
}
for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
next;
}
- $i++;
+ #Skip CCS and ServerHello
+ $i += 2;
${$proxy->record_list}[$i]->outer_content_type(TLSProxy::Record::RT_HANDSHAKE);
}
0x04, 0x05;
foreach my $message (@{$proxy->message_list}) {
- if ($message->mt == TLSProxy::Message::MT_HELLO_RETRY_REQUEST
+ if ($message->mt == TLSProxy::Message::MT_SERVER_HELLO
&& ${$message->records}[0]->flight == 1) {
$message->delete_extension(TLSProxy::Message::EXT_KEY_SHARE)
if ($testtype == COOKIE_ONLY);
@handmessages = (
[TLSProxy::Message::MT_CLIENT_HELLO,
checkhandshake::ALL_HANDSHAKES],
- [TLSProxy::Message::MT_HELLO_RETRY_REQUEST,
+ [TLSProxy::Message::MT_SERVER_HELLO,
checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
[TLSProxy::Message::MT_CLIENT_HELLO,
checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
[TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
checkhandshake::PSK_CLI_EXTENSION],
- [TLSProxy::Message::MT_HELLO_RETRY_REQUEST, TLSProxy::Message::EXT_KEY_SHARE,
+ [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
checkhandshake::KEY_SHARE_HRR_EXTENSION],
[TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
@handmessages = (
[TLSProxy::Message::MT_CLIENT_HELLO,
checkhandshake::ALL_HANDSHAKES],
- [TLSProxy::Message::MT_HELLO_RETRY_REQUEST,
+ [TLSProxy::Message::MT_SERVER_HELLO,
checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
[TLSProxy::Message::MT_CLIENT_HELLO,
checkhandshake::HRR_HANDSHAKE | checkhandshake::HRR_RESUME_HANDSHAKE],
[TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_PSK,
checkhandshake::PSK_CLI_EXTENSION],
- [TLSProxy::Message::MT_HELLO_RETRY_REQUEST, TLSProxy::Message::EXT_KEY_SHARE,
+ [TLSProxy::Message::MT_SERVER_HELLO, TLSProxy::Message::EXT_KEY_SHARE,
checkhandshake::KEY_SHARE_HRR_EXTENSION],
[TLSProxy::Message::MT_CLIENT_HELLO, TLSProxy::Message::EXT_SERVER_NAME,
checkhandshake($proxy, checkhandshake::DEFAULT_HANDSHAKE,
checkhandshake::DEFAULT_EXTENSIONS
| checkhandshake::SUPPORTED_GROUPS_SRV_EXTENSION,
- "Default handshake test");
+ "Acceptable but non preferred key_share");
unlink $session;
+++ /dev/null
-# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
-#
-# Licensed under the OpenSSL license (the "License"). You may not use
-# this file except in compliance with the License. You can obtain a copy
-# in the file LICENSE in the source distribution or at
-# https://www.openssl.org/source/license.html
-
-use strict;
-
-package TLSProxy::HelloRetryRequest;
-
-use vars '@ISA';
-push @ISA, 'TLSProxy::Message';
-
-sub new
-{
- my $class = shift;
- my ($server,
- $data,
- $records,
- $startoffset,
- $message_frag_lens) = @_;
-
- my $self = $class->SUPER::new(
- $server,
- TLSProxy::Message::MT_HELLO_RETRY_REQUEST,
- $data,
- $records,
- $startoffset,
- $message_frag_lens);
-
- $self->{extension_data} = "";
-
- return $self;
-}
-
-sub parse
-{
- my $self = shift;
- my $ptr = 2;
-
- TLSProxy::Proxy->is_tls13(1);
-
- 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;
- }
-
- my $ciphersuite = unpack('n', substr($self->data, $ptr));
- $ptr += 2;
-
- my $extensions_len = unpack('n', substr($self->data, $ptr));
- if (!defined $extensions_len) {
- $extensions_len = 0;
- }
-
- $ptr += 2;
- my $extension_data;
- if ($extensions_len != 0) {
- $extension_data = substr($self->data, $ptr);
-
- if (length($extension_data) != $extensions_len) {
- die "Invalid extension length\n";
- }
- } else {
- if (length($self->data) != 2) {
- die "Invalid extension length\n";
- }
- $extension_data = "";
- }
- my %extensions = ();
- while (length($extension_data) >= 4) {
- my ($type, $size) = unpack("nn", $extension_data);
- my $extdata = substr($extension_data, 4, $size);
- $extension_data = substr($extension_data, 4 + $size);
- $extensions{$type} = $extdata;
- }
-
- $self->server_version($server_version);
- $self->ciphersuite($ciphersuite);
- $self->extension_data(\%extensions);
-
- print " Server Version:".$server_version."\n";
- print " Ciphersuite:".$ciphersuite."\n";
- print " Extensions Len:".$extensions_len."\n";
-}
-
-#Reconstruct the on-the-wire message data following changes
-sub set_message_contents
-{
- my $self = shift;
- my $data;
- my $extensions = "";
-
- foreach my $key (keys %{$self->extension_data}) {
- my $extdata = ${$self->extension_data}{$key};
- $extensions .= pack("n", $key);
- $extensions .= pack("n", length($extdata));
- $extensions .= $extdata;
- if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) {
- $extensions .= pack("n", $key);
- $extensions .= pack("n", length($extdata));
- $extensions .= $extdata;
- }
- }
-
- $data = pack('n', $self->server_version);
- $data .= pack('n', $self->ciphersuite);
- $data .= pack('n', length($extensions));
- $data .= $extensions;
- $self->data($data);
-}
-
-#Read/write accessors
-sub server_version
-{
- my $self = shift;
- if (@_) {
- $self->{server_version} = shift;
- }
- return $self->{server_version};
-}
-sub ciphersuite
-{
- my $self = shift;
- if (@_) {
- $self->{ciphersuite} = shift;
- }
- return $self->{ciphersuite};
-}
-sub extension_data
-{
- my $self = shift;
- if (@_) {
- $self->{extension_data} = shift;
- }
- return $self->{extension_data};
-}
-sub set_extension
-{
- my ($self, $ext_type, $ext_data) = @_;
- $self->{extension_data}{$ext_type} = $ext_data;
-}
-sub delete_extension
-{
- my ($self, $ext_type) = @_;
- delete $self->{extension_data}{$ext_type};
-}
-1;
MT_CLIENT_HELLO => 1,
MT_SERVER_HELLO => 2,
MT_NEW_SESSION_TICKET => 4,
- MT_HELLO_RETRY_REQUEST => 6,
MT_ENCRYPTED_EXTENSIONS => 8,
MT_CERTIFICATE => 11,
MT_SERVER_KEY_EXCHANGE => 12,
MT_CLIENT_HELLO, "ClientHello",
MT_SERVER_HELLO, "ServerHello",
MT_NEW_SESSION_TICKET, "NewSessionTicket",
- MT_HELLO_RETRY_REQUEST, "HelloRetryRequest",
MT_ENCRYPTED_EXTENSIONS, "EncryptedExtensions",
MT_CERTIFICATE, "Certificate",
MT_SERVER_KEY_EXCHANGE, "ServerKeyExchange",
[@message_frag_lens]
);
$message->parse();
- } elsif ($mt == MT_HELLO_RETRY_REQUEST) {
- $message = TLSProxy::HelloRetryRequest->new(
- $server,
- $data,
- [@message_rec_list],
- $startoffset,
- [@message_frag_lens]
- );
- $message->parse();
} elsif ($mt == MT_SERVER_HELLO) {
$message = TLSProxy::ServerHello->new(
$server,
use TLSProxy::Record;
use TLSProxy::Message;
use TLSProxy::ClientHello;
-use TLSProxy::HelloRetryRequest;
use TLSProxy::ServerHello;
use TLSProxy::EncryptedExtensions;
use TLSProxy::Certificate;
my $extcount;
my $clienthelloseen = 0;
+ my $lastmt = 0;
+ my $numsh = 0;
+ if (TLSProxy::Proxy::is_tls13()) {
+ #How many ServerHellos are we expecting?
+ for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) {
+ next if (($handmessages[$loop][1] & $handtype) == 0);
+ $numsh++ if ($lastmt != TLSProxy::Message::MT_SERVER_HELLO
+ && $handmessages[$loop][0] == TLSProxy::Message::MT_SERVER_HELLO);
+ $lastmt = $handmessages[$loop][0];
+ }
+ }
+
#First count the number of tests
my $nextmess = 0;
my $message = undef;
my $chnum = 0;
+ my $shnum = 0;
+ if (!TLSProxy::Proxy::is_tls13()) {
+ # In non-TLSv1.3 we always treat reneg CH and SH like the first CH
+ # and SH
+ $chnum = 1;
+ $shnum = 1;
+ }
+ #If we're only expecting one ServerHello out of two then we skip the
+ #first ServerHello in the list completely
+ $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13());
+ $loop = 0;
for ($numtests = 0; $handmessages[$loop][1] != 0; $loop++) {
next if (($handmessages[$loop][1] & $handtype) == 0);
if (scalar @{$proxy->message_list} > $nextmess) {
$numtests++;
next if (!defined $message);
- $chnum = 1 if $message->mt() != TLSProxy::Message::MT_CLIENT_HELLO
- && TLSProxy::Proxy::is_tls13();
+ if (TLSProxy::Proxy::is_tls13()) {
+ $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO;
+ $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO;
+ }
next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO
- && $message->mt() != TLSProxy::Message::MT_HELLO_RETRY_REQUEST
&& $message->mt() != TLSProxy::Message::MT_SERVER_HELLO
&& $message->mt() !=
TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS
next if $message->mt() == TLSProxy::Message::MT_CERTIFICATE
&& !TLSProxy::Proxy::is_tls13();
- my $extchnum = 0;
+ my $extchnum = 1;
+ my $extshnum = 1;
for (my $extloop = 0;
$extensions[$extloop][2] != 0;
$extloop++) {
- $extchnum = 1 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO
+ $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO
&& TLSProxy::Proxy::is_tls13();
+ $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO
+ && $extchnum == 2;
next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO
&& $extchnum != $chnum;
+ next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO
+ && $extshnum != $shnum;
next if ($message->mt() != $extensions[$extloop][0]);
$numtests++;
}
$nextmess = 0;
$message = undef;
- $chnum = 0;
+ if (TLSProxy::Proxy::is_tls13()) {
+ $chnum = 0;
+ $shnum = 0;
+ } else {
+ # In non-TLSv1.3 we always treat reneg CH and SH like the first CH
+ # and SH
+ $chnum = 1;
+ $shnum = 1;
+ }
+ #If we're only expecting one ServerHello out of two then we skip the
+ #first ServerHello in the list completely
+ $shnum++ if ($numsh == 1 && TLSProxy::Proxy::is_tls13());
for ($loop = 0; $handmessages[$loop][1] != 0; $loop++) {
next if (($handmessages[$loop][1] & $handtype) == 0);
if (scalar @{$proxy->message_list} > $nextmess) {
"Message type check. Got ".$message->mt
.", expected ".$handmessages[$loop][0]);
}
- $chnum = 1 if $message->mt() != TLSProxy::Message::MT_CLIENT_HELLO
- && TLSProxy::Proxy::is_tls13();
+ if (TLSProxy::Proxy::is_tls13()) {
+ $chnum++ if $message->mt() == TLSProxy::Message::MT_CLIENT_HELLO;
+ $shnum++ if $message->mt() == TLSProxy::Message::MT_SERVER_HELLO;
+ }
next if ($message->mt() != TLSProxy::Message::MT_CLIENT_HELLO
- && $message->mt() != TLSProxy::Message::MT_HELLO_RETRY_REQUEST
&& $message->mt() != TLSProxy::Message::MT_SERVER_HELLO
&& $message->mt() !=
TLSProxy::Message::MT_ENCRYPTED_EXTENSIONS
}
#Now check that we saw the extensions we expected
my $msgexts = $message->extension_data();
- my $extchnum = 0;
+ my $extchnum = 1;
+ my $extshnum = 1;
for (my $extloop = 0, $extcount = 0; $extensions[$extloop][2] != 0;
$extloop++) {
#In TLSv1.3 we can have two ClientHellos if there has been a
#HelloRetryRequest, and they may have different extensions. Skip
#if these are extensions for a different ClientHello
- $extchnum = 1 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO
+ $extchnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_CLIENT_HELLO
&& TLSProxy::Proxy::is_tls13();
+ $extshnum = 2 if $extensions[$extloop][0] != TLSProxy::Message::MT_SERVER_HELLO
+ && $extchnum == 2;
next if $extensions[$extloop][0] == TLSProxy::Message::MT_CLIENT_HELLO
&& $extchnum != $chnum;
+ next if $extensions[$extloop][0] == TLSProxy::Message::MT_SERVER_HELLO
+ && $extshnum != $shnum;
next if ($message->mt() != $extensions[$extloop][0]);
ok (($extensions[$extloop][2] & $exttype) == 0
|| defined ($msgexts->{$extensions[$extloop][1]}),