diff options
author | Daiki Ueno <ueno@gnu.org> | 2022-12-08 11:53:20 +0900 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2022-12-21 15:09:09 +0900 |
commit | 0aaa4015d2a1b41681d8d60bcb4b0a7b805515da (patch) | |
tree | 47d48b85a8171fddeffa1d4d53f119f3fd2dc4eb /lib | |
parent | 9e2ccc12a56181c1cf6dea5bd898c703ecbc9652 (diff) | |
download | gnutls-0aaa4015d2a1b41681d8d60bcb4b0a7b805515da.tar.gz |
record: enable check on CCS content also in TLS 1.2
This generilizes the value check of Change Cipher Spec for all TLS
protocol versions including TLS 1.2 or earlier. It also fixes the
logic of the check so the value is decrypted before being examined,
according to the RFC.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/record.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/lib/record.c b/lib/record.c index aad128e1f2..53adc83076 100644 --- a/lib/record.c +++ b/lib/record.c @@ -854,6 +854,16 @@ record_add_to_buffers(gnutls_session_t session, goto unexpected_packet; } + /* if the CCS has value other than 1 abort the connection, + * unless old DTLS is negotiated, where CCS includes a sequence + * number */ + if (type == GNUTLS_CHANGE_CIPHER_SPEC && + !(ver && ver->id == GNUTLS_DTLS0_9) && + (bufel->msg.size != 1 || bufel->msg.data[0] != 1)) { + ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + goto unexpected_packet; + } + _gnutls_record_buffer_put(session, type, seq, bufel); /* if we received application data as expected then we @@ -919,6 +929,15 @@ record_add_to_buffers(gnutls_session_t session, goto cleanup; } + /* if the CCS has value other than 1 abort the + * connection, unless old DTLS is negotiated, where CCS + * includes a sequence number */ + if (!(ver && ver->id == GNUTLS_DTLS0_9) && + (bufel->msg.size != 1 || bufel->msg.data[0] != 1)) { + ret = gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET); + goto unexpected_packet; + } + _gnutls_record_buffer_put(session, recv->type, seq, bufel); @@ -1351,15 +1370,13 @@ _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) { - /* 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) + /* ignore CCS if TLS 1.3 is negotiated */ + if (record.type == GNUTLS_CHANGE_CIPHER_SPEC && vers && vers->tls13_sem) { + /* if the CCS has arrived after Finished, abort the + * connection */ + if (!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 */ |