mirror of
https://github.com/openssl/openssl.git
synced 2025-04-06 20:20:50 +08:00
Provide an SSL_read_early() function for reading early data
Reviewed-by: Rich Salz <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/2737)
This commit is contained in:
parent
6cb422654d
commit
d781d247d1
@ -1611,6 +1611,12 @@ __owur int SSL_accept(SSL *ssl);
|
||||
__owur int SSL_connect(SSL *ssl);
|
||||
__owur int SSL_read(SSL *ssl, void *buf, int num);
|
||||
__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
|
||||
|
||||
# define SSL_READ_EARLY_ERROR 0
|
||||
# define SSL_READ_EARLY_SUCCESS 1
|
||||
# define SSL_READ_EARLY_FINISH 2
|
||||
|
||||
__owur int SSL_read_early(SSL *s, void *buf, size_t num, size_t *readbytes);
|
||||
__owur int SSL_peek(SSL *ssl, void *buf, int num);
|
||||
__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
|
||||
__owur int SSL_write(SSL *ssl, const void *buf, int num);
|
||||
@ -2255,6 +2261,7 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_SSL_PEEK_EX 432
|
||||
# define SSL_F_SSL_PEEK_INTERNAL 522
|
||||
# define SSL_F_SSL_READ 223
|
||||
# define SSL_F_SSL_READ_EARLY 529
|
||||
# define SSL_F_SSL_READ_EX 434
|
||||
# define SSL_F_SSL_READ_INTERNAL 523
|
||||
# define SSL_F_SSL_RENEGOTIATE 516
|
||||
@ -2330,7 +2337,7 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_F_TLS_CONSTRUCT_CLIENT_VERIFY 489
|
||||
# define SSL_F_TLS_CONSTRUCT_CTOS_ALPN 466
|
||||
# define SSL_F_TLS_CONSTRUCT_CTOS_CERTIFICATE 355
|
||||
# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA 521
|
||||
# define SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA 530
|
||||
# define SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS 467
|
||||
# define SSL_F_TLS_CONSTRUCT_CTOS_EMS 468
|
||||
# define SSL_F_TLS_CONSTRUCT_CTOS_ETM 469
|
||||
@ -2669,6 +2676,7 @@ int ERR_load_SSL_strings(void);
|
||||
# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239
|
||||
# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242
|
||||
# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243
|
||||
# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178
|
||||
# define SSL_R_UNEXPECTED_MESSAGE 244
|
||||
# define SSL_R_UNEXPECTED_RECORD 245
|
||||
# define SSL_R_UNINITIALIZED 276
|
||||
|
@ -1437,6 +1437,14 @@ int ssl3_read_bytes(SSL *s, int type, int *recvd_type, unsigned char *buf,
|
||||
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];
|
||||
|
@ -419,15 +419,15 @@ int ssl3_get_record(SSL *s)
|
||||
|
||||
/*-
|
||||
* enc_err is:
|
||||
* 0: (in non-constant time) if the record is publically invalid.
|
||||
* 0: (in non-constant time) if the record is publicly invalid.
|
||||
* 1: if the padding is valid
|
||||
* -1: if the padding is invalid
|
||||
*/
|
||||
if (enc_err == 0) {
|
||||
if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
|
||||
/*
|
||||
* We assume this is unreadable early_data - we treat it like an
|
||||
* empty record
|
||||
* Valid early_data that we cannot decrypt might fail here as
|
||||
* publicly invalid. We treat it like an empty record.
|
||||
*/
|
||||
thisrr = &rr[0];
|
||||
thisrr->length = 0;
|
||||
@ -507,6 +507,17 @@ int ssl3_get_record(SSL *s)
|
||||
}
|
||||
|
||||
if (enc_err < 0) {
|
||||
if (num_recs == 1 && ossl_statem_skip_early_data(s)) {
|
||||
/*
|
||||
* We assume this is unreadable early_data - we treat it like an
|
||||
* empty record
|
||||
*/
|
||||
thisrr = &rr[0];
|
||||
thisrr->length = 0;
|
||||
thisrr->read = 1;
|
||||
RECORD_LAYER_set_numrpipes(&s->rlayer, 1);
|
||||
return 1;
|
||||
}
|
||||
/*
|
||||
* A separate 'decryption_failed' alert was introduced with TLS 1.0,
|
||||
* SSL 3.0 only has 'bad_record_mac'. But unless a decryption
|
||||
|
@ -205,6 +205,7 @@ static ERR_STRING_DATA SSL_str_functs[] = {
|
||||
{ERR_FUNC(SSL_F_SSL_PEEK_EX), "SSL_peek_ex"},
|
||||
{ERR_FUNC(SSL_F_SSL_PEEK_INTERNAL), "ssl_peek_internal"},
|
||||
{ERR_FUNC(SSL_F_SSL_READ), "SSL_read"},
|
||||
{ERR_FUNC(SSL_F_SSL_READ_EARLY), "SSL_read_early"},
|
||||
{ERR_FUNC(SSL_F_SSL_READ_EX), "SSL_read_ex"},
|
||||
{ERR_FUNC(SSL_F_SSL_READ_INTERNAL), "ssl_read_internal"},
|
||||
{ERR_FUNC(SSL_F_SSL_RENEGOTIATE), "SSL_renegotiate"},
|
||||
@ -793,6 +794,8 @@ static ERR_STRING_DATA SSL_str_reasons[] = {
|
||||
"unable to load ssl3 md5 routines"},
|
||||
{ERR_REASON(SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
|
||||
"unable to load ssl3 sha1 routines"},
|
||||
{ERR_REASON(SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
|
||||
"unexpected end of early data"},
|
||||
{ERR_REASON(SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
|
||||
{ERR_REASON(SSL_R_UNEXPECTED_RECORD), "unexpected record"},
|
||||
{ERR_REASON(SSL_R_UNINITIALIZED), "uninitialized"},
|
||||
|
@ -1594,6 +1594,75 @@ int SSL_read_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int SSL_read_early(SSL *s, void *buf, size_t num, size_t *readbytes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!s->server) {
|
||||
SSLerr(SSL_F_SSL_READ_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return SSL_READ_EARLY_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO(TLS1.3): Somehow we need to check that we're not receiving too much
|
||||
* data
|
||||
*/
|
||||
|
||||
switch (s->early_data_state) {
|
||||
case SSL_EARLY_DATA_NONE:
|
||||
if (!SSL_in_before(s)) {
|
||||
SSLerr(SSL_F_SSL_READ_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return SSL_READ_EARLY_ERROR;
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case SSL_EARLY_DATA_ACCEPT_RETRY:
|
||||
s->early_data_state = SSL_EARLY_DATA_ACCEPTING;
|
||||
ret = SSL_accept(s);
|
||||
if (ret <= 0) {
|
||||
/* NBIO or error */
|
||||
s->early_data_state = SSL_EARLY_DATA_ACCEPT_RETRY;
|
||||
return SSL_READ_EARLY_ERROR;
|
||||
}
|
||||
/* fall through */
|
||||
|
||||
case SSL_EARLY_DATA_READ_RETRY:
|
||||
if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
|
||||
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
|
||||
*/
|
||||
if (ret > 0 || (ret <= 0 && s->early_data_state
|
||||
!= SSL_EARLY_DATA_FINISHED_READING)) {
|
||||
s->early_data_state = SSL_EARLY_DATA_READ_RETRY;
|
||||
return ret > 0 ? SSL_READ_EARLY_SUCCESS : SSL_READ_EARLY_ERROR;
|
||||
}
|
||||
} else {
|
||||
s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
|
||||
}
|
||||
*readbytes = 0;
|
||||
ossl_statem_set_in_init(s, 1);
|
||||
return SSL_READ_EARLY_FINISH;
|
||||
|
||||
default:
|
||||
SSLerr(SSL_F_SSL_READ_EARLY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return SSL_READ_EARLY_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
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_FINISHED_READING;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
|
||||
{
|
||||
if (s->handshake_func == NULL) {
|
||||
|
@ -618,7 +618,12 @@ typedef enum {
|
||||
SSL_EARLY_DATA_CONNECTING,
|
||||
SSL_EARLY_DATA_WRITE_RETRY,
|
||||
SSL_EARLY_DATA_WRITING,
|
||||
SSL_EARLY_DATA_FINISHED_WRITING
|
||||
SSL_EARLY_DATA_FINISHED_WRITING,
|
||||
SSL_EARLY_DATA_ACCEPT_RETRY,
|
||||
SSL_EARLY_DATA_ACCEPTING,
|
||||
SSL_EARLY_DATA_READ_RETRY,
|
||||
SSL_EARLY_DATA_READING,
|
||||
SSL_EARLY_DATA_FINISHED_READING
|
||||
} SSL_EARLY_DATA_STATE;
|
||||
|
||||
#define MAX_COMPRESSIONS_SIZE 255
|
||||
@ -1987,6 +1992,7 @@ static ossl_inline int ssl_has_cert(const SSL *s, int idx)
|
||||
|
||||
# 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);
|
||||
|
@ -326,7 +326,8 @@ static int state_machine(SSL *s, int server)
|
||||
}
|
||||
|
||||
if ((SSL_IS_FIRST_HANDSHAKE(s)
|
||||
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
|
||||
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING
|
||||
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_READING)
|
||||
|| s->renegotiate) {
|
||||
if (!tls_setup_handshake(s)) {
|
||||
ossl_statem_set_error(s);
|
||||
|
@ -1229,12 +1229,6 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
|
||||
SSL_COMP *comp;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is a real handshake so make sure we clean it up at the end. We set
|
||||
* this here so that we are after any early_data
|
||||
*/
|
||||
s->statem.cleanuphand = 1;
|
||||
|
||||
if (!PACKET_get_net_2(pkt, &sversion)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
SSLerr(SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_LENGTH_MISMATCH);
|
||||
|
@ -654,6 +654,10 @@ MSG_PROCESS_RETURN tls_process_finished(SSL *s, PACKET *pkt)
|
||||
int al = SSL_AD_INTERNAL_ERROR;
|
||||
size_t md_len;
|
||||
|
||||
|
||||
/* This is a real handshake so make sure we clean it up at the end */
|
||||
s->statem.cleanuphand = 1;
|
||||
|
||||
/* If this occurs, we have missed a message */
|
||||
if (!SSL_IS_TLS13(s) && !s->s3->change_cipher_spec) {
|
||||
al = SSL_AD_UNEXPECTED_MESSAGE;
|
||||
@ -944,6 +948,7 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
|
||||
s->d1->next_handshake_write_seq = 0;
|
||||
dtls1_clear_received_buffer(s);
|
||||
}
|
||||
s->early_data_state = SSL_EARLY_DATA_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -406,6 +406,10 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
|
||||
return WRITE_TRAN_ERROR;
|
||||
|
||||
case TLS_ST_OK:
|
||||
if (s->early_data_state == SSL_EARLY_DATA_FINISHED_READING) {
|
||||
st->hand_state = TLS_ST_SW_FINISHED;
|
||||
return WRITE_TRAN_FINISHED;
|
||||
}
|
||||
if (s->key_update != SSL_KEY_UPDATE_NONE) {
|
||||
st->hand_state = TLS_ST_SW_KEY_UPDATE;
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
@ -450,6 +454,11 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
|
||||
case TLS_ST_SW_FINISHED:
|
||||
if (s->early_data_state == SSL_EARLY_DATA_ACCEPTING) {
|
||||
st->hand_state = TLS_ST_OK;
|
||||
ossl_statem_set_in_init(s, 0);
|
||||
return WRITE_TRAN_CONTINUE;
|
||||
}
|
||||
return WRITE_TRAN_FINISHED;
|
||||
|
||||
case TLS_ST_SR_FINISHED:
|
||||
@ -1234,9 +1243,6 @@ MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
|
||||
s->new_session = 1;
|
||||
}
|
||||
|
||||
/* This is a real handshake so make sure we clean it up at the end */
|
||||
s->statem.cleanuphand = 1;
|
||||
|
||||
/*
|
||||
* First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure.
|
||||
*/
|
||||
|
@ -430,3 +430,4 @@ SSL_get_max_early_data 430 1_1_1 EXIST::FUNCTION:
|
||||
SSL_CTX_get_max_early_data 431 1_1_1 EXIST::FUNCTION:
|
||||
SSL_write_early 432 1_1_1 EXIST::FUNCTION:
|
||||
SSL_write_early_finish 433 1_1_1 EXIST::FUNCTION:
|
||||
SSL_read_early 434 1_1_1 EXIST::FUNCTION:
|
||||
|
Loading…
x
Reference in New Issue
Block a user