TLS_ST_SR_KEY_UPDATE,
TLS_ST_CR_KEY_UPDATE,
TLS_ST_EARLY_DATA,
- TLS_ST_PENDING_EARLY_DATA_END
+ TLS_ST_PENDING_EARLY_DATA_END,
+ TLS_ST_CW_END_OF_EARLY_DATA,
+ TLS_ST_SR_END_OF_EARLY_DATA
} OSSL_HANDSHAKE_STATE;
/*
# define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
# define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
# define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
-# define SSL_AD_END_OF_EARLY_DATA TLS13_AD_END_OF_EARLY_DATA
# define SSL_AD_MISSING_EXTENSION TLS13_AD_MISSING_EXTENSION
# define SSL_AD_CERTIFICATE_REQUIRED TLS13_AD_CERTIFICATE_REQUIRED
# define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
# define SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP 482
# define SSL_F_TLS_CONSTRUCT_CTOS_VERIFY 358
# define SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS 443
+# define SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA 536
# define SSL_F_TLS_CONSTRUCT_EXTENSIONS 447
# define SSL_F_TLS_CONSTRUCT_FINISHED 359
# define SSL_F_TLS_CONSTRUCT_HELLO_REQUEST 373
# define SSL_F_TLS_PROCESS_CLIENT_HELLO 381
# define SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE 382
# define SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS 444
+# define SSL_F_TLS_PROCESS_END_OF_EARLY_DATA 537
# define SSL_F_TLS_PROCESS_FINISHED 364
# define SSL_F_TLS_PROCESS_HELLO_REQ 507
# define SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST 511
# define SSL3_MT_CLIENT_HELLO 1
# 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
SSL3_RECORD_set_length(thiswr, len);
}
- if (s->early_data_state == SSL_EARLY_DATA_WRITING) {
+ if (s->early_data_state == SSL_EARLY_DATA_WRITING
+ || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
/*
* We haven't actually negotiated the version yet, but we're trying to
* send early data - so we need to use the the tls13enc function.
n = SSL3_RECORD_get_length(rr); /* available bytes */
/* now move 'n' bytes: */
- while (n-- > 0) {
- dest[(*dest_len)++] =
- SSL3_RECORD_get_data(rr)[SSL3_RECORD_get_off(rr)];
- SSL3_RECORD_add_off(rr, 1);
- SSL3_RECORD_add_length(rr, -1);
- }
-
- if (*dest_len < dest_maxlen) {
+ memcpy(dest + *dest_len,
+ SSL3_RECORD_get_data(rr) + SSL3_RECORD_get_off(rr), n);
+ SSL3_RECORD_add_off(rr, n);
+ SSL3_RECORD_add_length(rr, -n);
+ *dest_len += n;
+ if (SSL3_RECORD_get_length(rr) == 0)
SSL3_RECORD_set_read(rr);
+
+ if (*dest_len < dest_maxlen)
goto start; /* fragment was too small */
- }
}
}
al = SSL_AD_HANDSHAKE_FAILURE;
SSLerr(SSL_F_SSL3_READ_BYTES, SSL_R_NO_RENEGOTIATION);
goto f_err;
- } else if (alert_descr == SSL_AD_END_OF_EARLY_DATA) {
- if (!ssl_end_of_early_data_seen(s)) {
- al = SSL_AD_UNEXPECTED_MESSAGE;
- SSLerr(SSL_F_SSL3_READ_BYTES,
- SSL_R_UNEXPECTED_END_OF_EARLY_DATA);
- goto f_err;
- }
- return 0;
}
} else if (alert_level == SSL3_AL_FATAL) {
char tmp[16];
*/
if ((s->rlayer.handshake_fragment_len >= 4)
&& !ossl_statem_get_in_handshake(s)) {
- /*
- * To get here we must be trying to read app data but found handshake
- * data. But if we're trying to read app data, and we're not in init
- * (which is tested for at the top of this function) then init must be
- * finished
- */
- assert(SSL_is_init_finished(s));
- if (!SSL_is_init_finished(s)) {
- al = SSL_AD_INTERNAL_ERROR;
- SSLerr(SSL_F_SSL3_READ_BYTES, ERR_R_INTERNAL_ERROR);
- goto f_err;
- }
-
/* We found handshake data, so we're going back into init */
ossl_statem_set_in_init(s, 1);
ivlen = EVP_CIPHER_CTX_iv_length(ctx);
- if (s->early_data_state == SSL_EARLY_DATA_WRITING) {
+ if (s->early_data_state == SSL_EARLY_DATA_WRITING
+ || s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
alg_enc = s->session->cipher->algorithm_enc;
} else {
/*
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_CTOS_VERIFY), "TLS_CONSTRUCT_CTOS_VERIFY"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_ENCRYPTED_EXTENSIONS),
"tls_construct_encrypted_extensions"},
+ {ERR_FUNC(SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA),
+ "tls_construct_end_of_early_data"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_EXTENSIONS), "tls_construct_extensions"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_FINISHED), "tls_construct_finished"},
{ERR_FUNC(SSL_F_TLS_CONSTRUCT_HELLO_REQUEST),
"tls_process_client_key_exchange"},
{ERR_FUNC(SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS),
"tls_process_encrypted_extensions"},
+ {ERR_FUNC(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA),
+ "tls_process_end_of_early_data"},
{ERR_FUNC(SSL_F_TLS_PROCESS_FINISHED), "tls_process_finished"},
{ERR_FUNC(SSL_F_TLS_PROCESS_HELLO_REQ), "tls_process_hello_req"},
{ERR_FUNC(SSL_F_TLS_PROCESS_HELLO_RETRY_REQUEST),
},
};
-static int ssl_write_early_finish(SSL *s);
-
static int dane_ctx_enable(struct dane_ctx_st *dctx)
{
const EVP_MD **mdevp;
s->early_data_state = SSL_EARLY_DATA_READING;
ret = SSL_read_ex(s, buf, num, readbytes);
/*
- * Record layer will call ssl_end_of_early_data_seen() if we see
- * that alert - which updates the early_data_state to
- * SSL_EARLY_DATA_FINISHED_READING
+ * State machine will update early_data_state to
+ * SSL_EARLY_DATA_FINISHED_READING if we get an EndOfEarlyData
+ * message
*/
if (ret > 0 || (ret <= 0 && s->early_data_state
!= SSL_EARLY_DATA_FINISHED_READING)) {
}
}
-int ssl_end_of_early_data_seen(SSL *s)
-{
- if (s->early_data_state == SSL_EARLY_DATA_READING
- || s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
- s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
- ossl_statem_finish_early_data(s);
- return 1;
- }
-
- return 0;
-}
-
int SSL_get_early_data_status(const SSL *s)
{
return s->ext.early_data;
return -1;
}
- if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
- /*
- * We're still writing early data. We need to stop that so we can write
- * normal data
- */
- if (!ssl_write_early_finish(s))
- return 0;
- } else if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
+ if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
}
}
-static int ssl_write_early_finish(SSL *s)
-{
- int ret;
-
- if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY) {
- SSLerr(SSL_F_SSL_WRITE_EARLY_FINISH, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
- return 0;
- }
-
- s->early_data_state = SSL_EARLY_DATA_WRITING;
- ret = ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_END_OF_EARLY_DATA);
- if (ret <= 0) {
- s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
- return 0;
- }
- s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
- /*
- * We set the enc_write_ctx back to NULL because we may end up writing
- * in cleartext again if we get a HelloRetryRequest from the server.
- */
- EVP_CIPHER_CTX_free(s->enc_write_ctx);
- s->enc_write_ctx = NULL;
- ossl_statem_set_in_init(s, 1);
- return 1;
-}
-
int SSL_shutdown(SSL *s)
{
/*
return -1;
}
- if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
- int edfin;
-
- edfin = ssl_write_early_finish(s);
- if (edfin <= 0)
- return edfin;
- }
ossl_statem_check_finish_init(s, -1);
s->method->ssl_renegotiate_check(s, 0);
&& (s)->method->version != TLS_ANY_VERSION)
# define SSL_TREAT_AS_TLS13(s) \
- (SSL_IS_TLS13(s) || (s)->early_data_state == SSL_EARLY_DATA_WRITING)
+ (SSL_IS_TLS13(s) || (s)->early_data_state == SSL_EARLY_DATA_WRITING \
+ || (s)->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
# define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3->tmp.finish_md_len == 0)
# ifndef OPENSSL_UNIT_TEST
-int ssl_end_of_early_data_seen(SSL *s);
__owur int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes);
__owur int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written);
void ssl_clear_cipher_ctx(SSL *s);
{
if (send == -1) {
if (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
- || s->statem.hand_state == TLS_ST_EARLY_DATA)
+ || s->statem.hand_state == TLS_ST_EARLY_DATA) {
ossl_statem_set_in_init(s, 1);
+ if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY) {
+ /*
+ * SSL_connect() or SSL_do_handshake() has been called directly.
+ * We don't allow any more writing of early data.
+ */
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ }
+ }
} else if (!s->server) {
- if ((send && s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
+ if ((send && (s->statem.hand_state == TLS_ST_PENDING_EARLY_DATA_END
+ || s->statem.hand_state == TLS_ST_EARLY_DATA)
&& s->early_data_state != SSL_EARLY_DATA_WRITING)
- || (!send && s->statem.hand_state == TLS_ST_EARLY_DATA))
+ || (!send && s->statem.hand_state == TLS_ST_EARLY_DATA)) {
ossl_statem_set_in_init(s, 1);
+ /*
+ * SSL_write() has been called directly. We don't allow any more
+ * writing of early data.
+ */
+ if (send && s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ }
} else {
if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING
&& s->statem.hand_state == TLS_ST_EARLY_DATA)
void ossl_statem_set_sctp_read_sock(SSL *s, int read_sock);
__owur int ossl_statem_in_sctp_read_sock(SSL *s);
#endif
-int ossl_statem_finish_early_data(SSL *s);
return WRITE_TRAN_CONTINUE;
case TLS_ST_CR_FINISHED:
- if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY)
+ if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
+ || s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING)
st->hand_state = TLS_ST_PENDING_EARLY_DATA_END;
else
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
return WRITE_TRAN_CONTINUE;
case TLS_ST_PENDING_EARLY_DATA_END:
+ if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
+ st->hand_state = TLS_ST_CW_END_OF_EARLY_DATA;
+ return WRITE_TRAN_CONTINUE;
+ }
+ /* Fall through */
+
+ case TLS_ST_CW_END_OF_EARLY_DATA:
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
}
break;
- case TLS_ST_EARLY_DATA:
case TLS_ST_PENDING_EARLY_DATA_END:
+ /*
+ * If we've been called by SSL_do_handshake()/SSL_write(), or we did not
+ * attempt to write early data before calling SSL_read() then we press
+ * on with the handshake. Otherwise we pause here.
+ */
+ if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING
+ || s->early_data_state == SSL_EARLY_DATA_NONE)
+ return WORK_FINISHED_CONTINUE;
+ /* Fall through */
+
+ case TLS_ST_EARLY_DATA:
case TLS_ST_OK:
return tls_finish_handshake(s, wst, 1);
}
}
break;
+ case TLS_ST_CW_END_OF_EARLY_DATA:
+ /*
+ * We set the enc_write_ctx back to NULL because we may end up writing
+ * in cleartext again if we get a HelloRetryRequest from the server.
+ */
+ EVP_CIPHER_CTX_free(s->enc_write_ctx);
+ s->enc_write_ctx = NULL;
+ break;
+
case TLS_ST_CW_KEY_EXCH:
if (tls_client_key_exchange_post_work(s) == 0)
return WORK_ERROR;
*mt = SSL3_MT_CLIENT_HELLO;
break;
+ case TLS_ST_CW_END_OF_EARLY_DATA:
+ *confunc = tls_construct_end_of_early_data;
+ *mt = SSL3_MT_END_OF_EARLY_DATA;
+ break;
+
+ case TLS_ST_PENDING_EARLY_DATA_END:
+ *confunc = NULL;
+ *mt = SSL3_MT_DUMMY;
+ break;
+
case TLS_ST_CW_CERT:
*confunc = tls_construct_client_certificate;
*mt = SSL3_MT_CERTIFICATE;
return 1;
}
+
+int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt)
+{
+ if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
+ && s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
+ SSLerr(SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
+ ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+ return 0;
+ }
+
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
+ return 1;
+}
s->d1->next_handshake_write_seq = 0;
dtls1_clear_received_buffer(s);
}
- s->early_data_state = SSL_EARLY_DATA_NONE;
}
/*
/* The spec allows for a longer length than this, but we limit it */
#define HELLO_VERIFY_REQUEST_MAX_LENGTH 258
+#define END_OF_EARLY_DATA_MAX_LENGTH 0
#define SERVER_HELLO_MAX_LENGTH 20000
#define HELLO_RETRY_REQUEST_MAX_LENGTH 20000
#define ENCRYPTED_EXTENSIONS_MAX_LENGTH 20000
#endif
__owur MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt);
+__owur int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt);
/* some server-only functions */
__owur MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt);
__owur MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt);
#endif
__owur int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt);
+MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt);
/* Extension processing */
break;
case TLS_ST_EARLY_DATA:
+ if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
+ if (mt == SSL3_MT_END_OF_EARLY_DATA) {
+ st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
+ return 1;
+ }
+ break;
+ }
+ /* Fall through */
+
+ case TLS_ST_SR_END_OF_EARLY_DATA:
case TLS_ST_SW_FINISHED:
if (s->s3->tmp.cert_request) {
if (mt == SSL3_MT_CERTIFICATE) {
}
/* No valid transition found */
- ssl3_send_alert(s, SSL3_AL_FATAL, SSL3_AD_UNEXPECTED_MESSAGE);
- SSLerr(SSL_F_OSSL_STATEM_SERVER13_READ_TRANSITION,
- SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
case TLS_ST_SR_CLNT_HELLO:
return CLIENT_HELLO_MAX_LENGTH;
+ case TLS_ST_SR_END_OF_EARLY_DATA:
+ return END_OF_EARLY_DATA_MAX_LENGTH;
+
case TLS_ST_SR_CERT:
return s->max_cert_list;
case TLS_ST_SR_CLNT_HELLO:
return tls_process_client_hello(s, pkt);
+ case TLS_ST_SR_END_OF_EARLY_DATA:
+ return tls_process_end_of_early_data(s, pkt);
+
case TLS_ST_SR_CERT:
return tls_process_client_certificate(s, pkt);
return WORK_FINISHED_CONTINUE;
}
-int ossl_statem_finish_early_data(SSL *s)
-{
- if (!s->method->ssl3_enc->change_cipher_state(s,
- SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ))
- return 0;
-
- return 1;
-}
-
#ifndef OPENSSL_NO_SRP
static int ssl_check_srp_ext_ClientHello(SSL *s, int *al)
{
return 1;
}
+
+MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
+{
+ int al = SSL_AD_INTERNAL_ERROR;
+
+ if (PACKET_remaining(pkt) != 0) {
+ al = SSL_AD_DECODE_ERROR;
+ SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, SSL_R_LENGTH_MISMATCH);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (s->early_data_state != SSL_EARLY_DATA_READING
+ && s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
+ SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ /*
+ * EndOfEarlyData signals a key change so the end of the message must be on
+ * a record boundary.
+ */
+ if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
+ al = SSL_AD_UNEXPECTED_MESSAGE;
+ SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
+ SSL_R_NOT_ON_RECORD_BOUNDARY);
+ goto err;
+ }
+
+ s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
+ if (!s->method->ssl3_enc->change_cipher_state(s,
+ SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
+ SSLerr(SSL_F_TLS_PROCESS_END_OF_EARLY_DATA, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ return MSG_PROCESS_CONTINUE_READING;
+ err:
+ ssl3_send_alert(s, SSL3_AL_FATAL, al);
+ ossl_statem_set_error(s);
+ return MSG_PROCESS_ERROR;
+}
int tls13_alert_code(int code)
{
- if (code == SSL_AD_MISSING_EXTENSION || code == SSL_AD_END_OF_EARLY_DATA)
+ if (code == SSL_AD_MISSING_EXTENSION)
return code;
return tls1_alert_code(code);
goto end;
}
- /*
- * We expect SSL_accept() to initially block as it handles the end of early
- * data alert
- */
- if (SSL_accept(serverssl) > 0) {
- printf("Unexpected success completing server handshake\n");
- goto end;
- }
-
if (SSL_accept(serverssl) <= 0) {
printf("Unable to complete server handshake\n");
goto end;