提交 30f05b19 编写于 作者: M Matt Caswell

Create the NewSessionTicket message in TLSv1.3

Reviewed-by: NRich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2259)
上级 b2f7e8c0
...@@ -602,7 +602,7 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst) ...@@ -602,7 +602,7 @@ WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
break; break;
case TLS_ST_OK: case TLS_ST_OK:
return tls_finish_handshake(s, wst); return tls_finish_handshake(s, wst, 1);
} }
return WORK_FINISHED_CONTINUE; return WORK_FINISHED_CONTINUE;
......
...@@ -821,7 +821,12 @@ unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk, ...@@ -821,7 +821,12 @@ unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt, CERT_PKEY *cpk,
return 1; return 1;
} }
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst) /*
* Tidy up after the end of a handshake. In the case of SCTP this may result
* in NBIO events. If |clearbufs| is set then init_buf and the wbio buffer is
* freed up as well.
*/
WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs)
{ {
void (*cb) (const SSL *ssl, int type, int val) = NULL; void (*cb) (const SSL *ssl, int type, int val) = NULL;
...@@ -834,28 +839,27 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst) ...@@ -834,28 +839,27 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
} }
#endif #endif
/* clean a few things up */ if (clearbufs) {
ssl3_cleanup_key_block(s); if (!SSL_IS_DTLS(s)) {
/*
if (!SSL_IS_DTLS(s)) { * We don't do this in DTLS because we may still need the init_buf
/* * in case there are any unexpected retransmits
* We don't do this in DTLS because we may still need the init_buf */
* in case there are any unexpected retransmits BUF_MEM_free(s->init_buf);
*/ s->init_buf = NULL;
BUF_MEM_free(s->init_buf); }
s->init_buf = NULL; ssl_free_wbio_buffer(s);
s->init_num = 0;
} }
ssl_free_wbio_buffer(s);
s->init_num = 0;
if (s->statem.cleanuphand) { if (s->statem.cleanuphand) {
/* skipped if we just sent a HelloRequest */ /* skipped if we just sent a HelloRequest */
s->renegotiate = 0; s->renegotiate = 0;
s->new_session = 0; s->new_session = 0;
s->statem.cleanuphand = 0; s->statem.cleanuphand = 0;
ssl3_cleanup_key_block(s);
if (s->server) { if (s->server) {
ssl_update_cache(s, SSL_SESS_CACHE_SERVER); ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
...@@ -887,6 +891,13 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst) ...@@ -887,6 +891,13 @@ WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst)
} }
} }
/*
* If we've not cleared the buffers its because we've got more work to do,
* so continue.
*/
if (!clearbufs)
return WORK_FINISHED_CONTINUE;
return WORK_FINISHED_STOP; return WORK_FINISHED_STOP;
} }
......
...@@ -107,7 +107,7 @@ __owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt); ...@@ -107,7 +107,7 @@ __owur int tls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
__owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt); __owur int dtls_construct_change_cipher_spec(SSL *s, WPACKET *pkt);
__owur int tls_construct_finished(SSL *s, WPACKET *pkt); __owur int tls_construct_finished(SSL *s, WPACKET *pkt);
__owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst); __owur WORK_STATE tls_finish_handshake(SSL *s, WORK_STATE wst, int clearbufs);
__owur WORK_STATE dtls_wait_for_dry(SSL *s); __owur WORK_STATE dtls_wait_for_dry(SSL *s);
/* some client-only functions */ /* some client-only functions */
......
...@@ -439,6 +439,18 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s) ...@@ -439,6 +439,18 @@ static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
return WRITE_TRAN_FINISHED; return WRITE_TRAN_FINISHED;
case TLS_ST_SR_FINISHED: case TLS_ST_SR_FINISHED:
/*
* Technically we have finished the handshake at this point, but we're
* going to remain "in_init" for now and write out the session ticket
* immediately.
* TODO(TLS1.3): Perhaps we need to be able to control this behaviour
* and give the application the opportunity to delay sending the
* session ticket?
*/
st->hand_state = TLS_ST_SW_SESSION_TICKET;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
st->hand_state = TLS_ST_OK; st->hand_state = TLS_ST_OK;
ossl_statem_set_in_init(s, 0); ossl_statem_set_in_init(s, 0);
return WRITE_TRAN_CONTINUE; return WRITE_TRAN_CONTINUE;
...@@ -626,7 +638,14 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst) ...@@ -626,7 +638,14 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
return WORK_FINISHED_CONTINUE; return WORK_FINISHED_CONTINUE;
case TLS_ST_SW_SESSION_TICKET: case TLS_ST_SW_SESSION_TICKET:
if (SSL_IS_DTLS(s)) { if (SSL_IS_TLS13(s)) {
/*
* 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.
*/
return tls_finish_handshake(s, wst, 0);
} if (SSL_IS_DTLS(s)) {
/* /*
* We're into the last flight. We don't retransmit the last flight * We're into the last flight. We don't retransmit the last flight
* unless we need to, so we don't use the timer * unless we need to, so we don't use the timer
...@@ -653,7 +672,7 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst) ...@@ -653,7 +672,7 @@ WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
return WORK_FINISHED_CONTINUE; return WORK_FINISHED_CONTINUE;
case TLS_ST_OK: case TLS_ST_OK:
return tls_finish_handshake(s, wst); return tls_finish_handshake(s, wst, 1);
} }
return WORK_FINISHED_CONTINUE; return WORK_FINISHED_CONTINUE;
...@@ -788,6 +807,11 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst) ...@@ -788,6 +807,11 @@ WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
return WORK_ERROR; return WORK_ERROR;
} }
break; break;
case TLS_ST_SW_SESSION_TICKET:
if (SSL_IS_TLS13(s) && statem_flush(s) != 1)
return WORK_MORE_A;
break;
} }
return WORK_FINISHED_CONTINUE; return WORK_FINISHED_CONTINUE;
...@@ -3219,8 +3243,12 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) ...@@ -3219,8 +3243,12 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
SSL_CTX *tctx = s->initial_ctx; SSL_CTX *tctx = s->initial_ctx;
unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[TLSEXT_KEYNAME_LENGTH]; unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
int iv_len; int iv_len, al = SSL_AD_INTERNAL_ERROR;
size_t macoffset, macendoffset; size_t macoffset, macendoffset;
union {
unsigned char age_add_c[sizeof(uint32_t)];
uint32_t age_add;
} age_add_u;
/* get session encoding length */ /* get session encoding length */
slen_full = i2d_SSL_SESSION(s->session, NULL); slen_full = i2d_SSL_SESSION(s->session, NULL);
...@@ -3313,12 +3341,18 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) ...@@ -3313,12 +3341,18 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
sizeof(tctx->ext.tick_key_name)); sizeof(tctx->ext.tick_key_name));
} }
if (SSL_IS_TLS13(s) && RAND_bytes(age_add_u.age_add_c,
sizeof(age_add_u)) <= 0)
goto err;
/* /*
* Ticket lifetime hint (advisory only): We leave this unspecified * Ticket lifetime hint (advisory only): We leave this unspecified
* for resumed session (for simplicity), and guess that tickets for * for resumed session (for simplicity), and guess that tickets for
* new sessions will live as long as their sessions. * new sessions will live as long as their sessions.
*/ */
if (!WPACKET_put_bytes_u32(pkt, s->hit ? 0 : s->session->timeout) if (!WPACKET_put_bytes_u32(pkt, s->hit ? 0 : s->session->timeout)
|| (SSL_IS_TLS13(s)
&& !WPACKET_put_bytes_u32(pkt, age_add_u.age_add))
/* Now the actual ticket data */ /* Now the actual ticket data */
|| !WPACKET_start_sub_packet_u16(pkt) || !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_get_total_written(pkt, &macoffset) || !WPACKET_get_total_written(pkt, &macoffset)
...@@ -3345,7 +3379,11 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt) ...@@ -3345,7 +3379,11 @@ int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
|| hlen > EVP_MAX_MD_SIZE || hlen > EVP_MAX_MD_SIZE
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2) || !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|| macdata1 != macdata2 || macdata1 != macdata2
|| !WPACKET_close(pkt)) { || !WPACKET_close(pkt)
|| (SSL_IS_TLS13(s)
&& !tls_construct_extensions(s, pkt,
EXT_TLS1_3_NEW_SESSION_TICKET,
NULL, 0, &al))) {
SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR); SSLerr(SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
goto err; goto err;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册