]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
record: enable check on CCS content also in TLS 1.2
authorDaiki Ueno <ueno@gnu.org>
Thu, 8 Dec 2022 02:53:20 +0000 (11:53 +0900)
committerDaiki Ueno <ueno@gnu.org>
Wed, 21 Dec 2022 06:09:09 +0000 (15:09 +0900)
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>
lib/record.c

index aad128e1f2c7f6e55a41aa4da6b771284882a951..53adc830760ba1445c905381006891d724b01360 100644 (file)
@@ -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 */