#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
break;
case TLS_ST_EARLY_DATA:
- if (s->hello_retry_request) {
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
if (mt == SSL3_MT_CLIENT_HELLO) {
st->hand_state = TLS_ST_SR_CLNT_HELLO;
return 1;
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;
+ 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;
+ case TLS_ST_SW_SRVR_HELLO:
+ if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
+ && s->hello_retry_request != SSL_HRR_COMPLETE)
+ st->hand_state = TLS_ST_SW_CHANGE;
+ else if (s->hello_retry_request == SSL_HRR_PENDING)
+ st->hand_state = TLS_ST_EARLY_DATA;
+ else
+ st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
return WRITE_TRAN_CONTINUE;
- case TLS_ST_SW_SRVR_HELLO:
- st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
+ case TLS_ST_SW_CHANGE:
+ if (s->hello_retry_request == SSL_HRR_PENDING)
+ st->hand_state = TLS_ST_EARLY_DATA;
+ else
+ st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
* Actually this is the end of the handshake, but we're going
* straight into writing the session ticket out. So we finish off
* the handshake, but keep the various buffers active.
- *
+ *
* Calls SSLfatal as required.
*/
return tls_finish_handshake(s, wst, 0);
break;
case TLS_ST_SW_CHANGE:
+ if (SSL_IS_TLS13(s))
+ break;
s->session->cipher = s->s3->tmp.new_cipher;
if (!s->method->ssl3_enc->setup_key_block(s)) {
/* SSLfatal() already called */
/* 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 == SSL_HRR_PENDING) {
+ if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
+ && statem_flush(s) != 1)
+ return WORK_MORE_A;
+ break;
+ }
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && s->hit) {
unsigned char sctpauthkey[64];
sizeof(sctpauthkey), sctpauthkey);
}
#endif
+ if (!SSL_IS_TLS13(s)
+ || ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
+ && s->hello_retry_request != SSL_HRR_COMPLETE))
+ break;
+ /* Fall through */
+
+ case TLS_ST_SW_CHANGE:
+ if (s->hello_retry_request == SSL_HRR_PENDING) {
+ if (!statem_flush(s))
+ return WORK_MORE_A;
+ break;
+ }
/*
* TODO(TLS1.3): This actually causes a problem. We don't yet know
* whether the next record we are going to receive is an unencrypted
/* SSLfatal() already called */
return WORK_ERROR;
}
+ break;
}
- break;
- case TLS_ST_SW_CHANGE:
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && !s->hit) {
/*
*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;
if (clienthello->isv2) {
unsigned int mt;
- if (!SSL_IS_FIRST_HANDSHAKE(s) || s->hello_retry_request) {
+ if (!SSL_IS_FIRST_HANDSHAKE(s)
+ || s->hello_retry_request != SSL_HRR_NONE) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
goto err;
SSL_R_NO_SHARED_CIPHER);
goto err;
}
- if (s->hello_retry_request
+ if (s->hello_retry_request == SSL_HRR_PENDING
&& (s->s3->tmp.new_cipher == NULL
|| s->s3->tmp.new_cipher->id != cipher->id)) {
/*
}
}
+ if (SSL_IS_TLS13(s)) {
+ memcpy(s->tmp_session_id, s->clienthello->session_id,
+ s->clienthello->session_id_len);
+ s->tmp_session_id_len = s->clienthello->session_id_len;
+ }
+
/*
* If it is a hit, check that the cipher is in the list. In TLSv1.3 we check
* ciphersuite compatibility with the session as part of resumption.
int compm;
size_t sl, len;
int version;
+ unsigned char *session_id;
+ int usetls13 = SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING;
- /* TODO(TLS1.3): Remove the DRAFT conditional before release */
- version = SSL_IS_TLS13(s) ? TLS1_3_VERSION_DRAFT : 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 == SSL_HRR_PENDING
+ ? 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;
* session ID.
* - However, if we want the new session to be single-use,
* we send back a 0-length session ID.
+ * - In TLSv1.3 we echo back the session id sent to us by the client
+ * regardless
* s->hit is non-zero in either case of session reuse,
* so the following won't overwrite an ID that we're supposed
* to send back.
&& !s->hit))
s->session->session_id_length = 0;
- sl = s->session->session_id_length;
+ if (usetls13) {
+ sl = s->tmp_session_id_len;
+ session_id = s->tmp_session_id;
+ } else {
+ sl = s->session->session_id_length;
+ session_id = s->session->session_id;
+ }
+
if (sl > sizeof(s->session->session_id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
ERR_R_INTERNAL_ERROR);
#ifdef OPENSSL_NO_COMP
compm = 0;
#else
- if (s->s3->tmp.new_compression == NULL)
+ if (usetls13 || 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, 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
- : SSL_EXT_TLS1_2_SERVER_HELLO,
+ s->hello_retry_request
+ == SSL_HRR_PENDING
+ ? 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 == SSL_HRR_PENDING) {
+ /* 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;
}
ERR_R_INTERNAL_ERROR);
goto err;
}
- /*
- * n is the length of the params, they start at &(d[4]) and p
- * points to the space at the end.
- */
-
/* Get length of the parameters we have written above */
if (!WPACKET_get_length(pkt, ¶mlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
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) {