diff options
-rw-r--r-- | lib/record.c | 11 | ||||
-rw-r--r-- | tests/tls13/change_cipher_spec.c | 15 |
2 files changed, 24 insertions, 2 deletions
diff --git a/lib/record.c b/lib/record.c index 19f5b52282..73c484ed56 100644 --- a/lib/record.c +++ b/lib/record.c @@ -1331,8 +1331,15 @@ _gnutls_recv_in_buffers(gnutls_session_t session, content_type_t type, if (bufel == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); - if (vers && vers->tls13_sem && record.type == GNUTLS_CHANGE_CIPHER_SPEC && - record.length == 1 && session->internals.handshake_in_progress) { + if (vers && vers->tls13_sem && record.type == GNUTLS_CHANGE_CIPHER_SPEC) { + /* if the CCS has value other than 0x01, or arrives + * after Finished, abort the connection */ + if (record.length != 1 || + *((uint8_t *) _mbuffer_get_udata_ptr(bufel) + + record.header_size) != 0x01 || + !session->internals.handshake_in_progress) + return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + _gnutls_read_log("discarding change cipher spec in TLS1.3\n"); /* we use the same mechanism to retry as when * receiving multiple empty TLS packets */ diff --git a/tests/tls13/change_cipher_spec.c b/tests/tls13/change_cipher_spec.c index 1a9b80c817..09ef786789 100644 --- a/tests/tls13/change_cipher_spec.c +++ b/tests/tls13/change_cipher_spec.c @@ -134,6 +134,11 @@ static void client(int fd, unsigned ccs_check) if (ret < 0) fail("client: recv did not succeed as expected: %s\n", gnutls_strerror(ret)); + /* send change cipher spec, this should fail in the server */ + do { + ret = send(fd, "\x14\x03\x03\x00\x01\x01", 6, 0); + } while(ret == -1 && (errno == EINTR || errno == EAGAIN)); + close(fd); gnutls_deinit(session); @@ -217,6 +222,7 @@ static void server(int fd, unsigned ccs_check) int ret; gnutls_session_t session; gnutls_certificate_credentials_t x509_cred; + char buf[64]; /* this must be called once in the program */ @@ -276,6 +282,15 @@ static void server(int fd, unsigned ccs_check) if (ret < 0) fail("server: gnutls_record_send did not succeed as expected: %s\n", gnutls_strerror(ret)); + /* receive CCS and fail */ + do { + ret = gnutls_record_recv(session, buf, sizeof(buf)); + } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); + + if (ret != GNUTLS_E_UNEXPECTED_PACKET) + fail("server: incorrect alert sent: %d != %d\n", + ret, GNUTLS_E_UNEXPECTED_PACKET); + close(fd); gnutls_deinit(session); |