summaryrefslogtreecommitdiff
path: root/lib/record.c
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@redhat.com>2018-07-19 15:52:26 +0200
committerNikos Mavrogiannopoulos <nmav@redhat.com>2018-08-03 09:18:17 +0200
commitd47111032f5b20eed70093d988741da5d0e69952 (patch)
treedb725ee0bf90d5d500a45c681bb07445574a8b86 /lib/record.c
parent5b9c6c93c680fdfa63b2854741d446ff50002510 (diff)
downloadgnutls-d47111032f5b20eed70093d988741da5d0e69952.tar.gz
tls1.3: server returns early on handshake when no cert is provided by client
Under TLS1.3 the server knows the negotiated keys early, if no client certificate is sent. In that case, the server is not only able to transmit the session ticket immediately after its finished message, but is also able to transmit data, similarly to false start. Resolves #481 Resolves #457 Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib/record.c')
-rw-r--r--lib/record.c54
1 files changed, 37 insertions, 17 deletions
diff --git a/lib/record.c b/lib/record.c
index 9b485fd293..1cc328cb93 100644
--- a/lib/record.c
+++ b/lib/record.c
@@ -1521,30 +1521,48 @@ check_session_status(gnutls_session_t session, unsigned ms)
return gnutls_assert_val(ret);
return GNUTLS_E_AGAIN;
+ case RECV_STATE_EARLY_START_HANDLING:
case RECV_STATE_FALSE_START_HANDLING:
return 1;
case RECV_STATE_FALSE_START:
/* if false start is not complete we always expect for handshake packets
* prior to anything else. */
- if (session->security_parameters.entity == GNUTLS_CLIENT &&
- (session->internals.flags & GNUTLS_ENABLE_FALSE_START)) {
- /* Attempt to complete handshake */
+ if (session->security_parameters.entity != GNUTLS_CLIENT ||
+ !(session->internals.flags & GNUTLS_ENABLE_FALSE_START))
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
- session->internals.recv_state = RECV_STATE_FALSE_START_HANDLING;
- ret = gnutls_handshake(session);
- if (ret < 0) {
- /* a temp or fatal error, make sure we reset the state
- * so we can resume or temp errors */
- session->internals.recv_state = RECV_STATE_FALSE_START;
- gnutls_assert();
- return ret;
- }
+ /* Attempt to complete handshake */
- session->internals.recv_state = RECV_STATE_0;
- return 1;
- } else {
+ session->internals.recv_state = RECV_STATE_FALSE_START_HANDLING;
+ ret = gnutls_handshake(session);
+ if (ret < 0) {
+ /* a temp or fatal error, make sure we reset the state
+ * so we can resume on temp errors */
+ session->internals.recv_state = RECV_STATE_FALSE_START;
+ return gnutls_assert_val(ret);
+ }
+
+ session->internals.recv_state = RECV_STATE_0;
+ return 1;
+ case RECV_STATE_EARLY_START:
+ /* if early start is not complete we always expect for handshake packets
+ * prior to anything else. */
+ if (session->security_parameters.entity != GNUTLS_SERVER ||
+ !(session->internals.flags & GNUTLS_ENABLE_EARLY_START))
return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+
+ /* Attempt to complete handshake */
+ session->internals.recv_state = RECV_STATE_EARLY_START_HANDLING;
+ ret = gnutls_handshake(session);
+ if (ret < 0) {
+ /* a temp or fatal error, make sure we reset the state
+ * so we can resume on temp errors */
+ session->internals.recv_state = RECV_STATE_EARLY_START;
+ return gnutls_assert_val(ret);
}
+
+ session->internals.recv_state = RECV_STATE_0;
+ return 1;
case RECV_STATE_DTLS_RETRANSMIT:
ret = _dtls_retransmit(session);
if (ret < 0)
@@ -1809,7 +1827,8 @@ gnutls_record_send2(gnutls_session_t session, const void *data,
/* this is to protect buggy applications from sending unencrypted
* data. We allow sending however, if we are in false start handshake
* state. */
- if (session->internals.recv_state != RECV_STATE_FALSE_START)
+ if (session->internals.recv_state != RECV_STATE_FALSE_START &&
+ session->internals.recv_state != RECV_STATE_EARLY_START)
return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
}
@@ -1984,7 +2003,8 @@ gnutls_record_recv(gnutls_session_t session, void *data, size_t data_size)
/* this is to protect buggy applications from sending unencrypted
* data. We allow sending however, if we are in false start handshake
* state. */
- if (session->internals.recv_state != RECV_STATE_FALSE_START)
+ if (session->internals.recv_state != RECV_STATE_FALSE_START &&
+ session->internals.recv_state != RECV_STATE_EARLY_START)
return gnutls_assert_val(GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE);
}