[gnutls-devel] GnuTLS | TLS-RFC Compliance (#1247)

Read-only notification of GnuTLS library development activities gnutls-devel at lists.gnutls.org
Fri Jun 4 14:35:49 CEST 2021

Marcel Maehren created an issue: https://gitlab.com/gnutls/gnutls/-/issues/1247

we (@jurajsomorovsky @ic0ns @mmaehren @XoMEX @Kavakuo) are performing an analysis of the RFC-compliance of open-source TLS implementations. Below we list our findings for this implementation. We admit that some are rather nit-picky, but we added them for the sake of completeness. We tried to keep the descriptions brief and didn’t want to spam the issues section so feel free to split up the list into individual issues as you see fit.
If you disagree with our interpretation of certain RFC statements, please leave feedback as we’re interested in your view.

Our results apply to the default configuration of version ***3.7.0***. We used the example implementations for client and server.

[S] = Applies to server
[C] = Applies to client
[C+S] = Applies to both

## Misc
- [S] GnuTLS accepts session resumption via session IDs even if the previous session has been terminated by a fatal alert
    - RFC 5246 - 7.2.2 Error Alerts
        > Thus, any connection terminated with a fatal alert MUST NOT be resumed.

- [S] GnuTLS server enforces that a TLS 1.3 client sends a key share for the first mutually supported group within the supported groups extension. As an example if a client offers secp521r1 and secp256r1 (in this order) but sends a key share for secp256r1, GnuTLS sends a HelloRetryRequest demanding a secp521r1 key share.

- [C] GnuTLS seems to struggle with very small records, i.e records with a fragment length of 1, when a HelloRetryRequest is sent.
    - These records yield a 'decode error' and GnuTLS prints "Fatal error: Error decoding the received TLS packet."
- [C] GnuTLS does not ignore the legacy version field in a ServerHello that negotiates TLS 1.3 and aborts the handshake for invalid values like 0x0304 or 0x0505
    - RFC 8446 - 4.2.1 Supported Versions
        > If this extension is present, clients MUST ignore the ServerHello.legacy_version value and MUST use only the "supported_versions" extension to determine the selected version.
    - Note that the RFC also defines that a server MUST use 0x0303 as the legacy version but specifically says that the client MUST ignore the field when SupportedVersions has been received
- [C+S] When encrypt-then-MAC is negotiated, GnuTLS does not validate the padding bytes

## Session not aborted

- [S] upon receiving a ClientHello with an unsolicited Cookie extension
    - RFC 8446 - 4.2.2 Cookie
        > Clients MUST NOT use cookies in their initial ClientHello in subsequent connections.

- [S] upon receiving a ClientHello proposing TLS 1.3 which does not use 0x0303 for the legacy version field 
    - RFC 8446 - 4.1.2 Client Hello
        > In TLS 1.3, the client indicates its version preferences in the "supported_versions" extension (Section 4.2.1) and the legacy_version field MUST be set to 0x0303, which is the version number for TLS 1.2.

- [C] upon receiving a ClientHello message interleaved with a warning alert
    - Note that this only applies if no HelloRetryRequest has been sent by the server. If a server sends an HRR and interleaves the subsequent ServerHello, GnuTLS closes the connection without an alert.
    - RFC 8446 - 5.1. Record Layer
        > Handshake messages MUST NOT be interleaved with other record types. That is, if a handshake message is split over two or more records, there MUST NOT be any other records between them.
- [C] upon receiving a TLS 1.3 HelloRetryRequest that does not result in any changes for the subsequent ClientHello
    - RFC 8446 - 4.1.4 Hello Retry Request
        > Clients MUST abort the handshake with an "illegal_parameter" alert if the HelloRetryRequest would not result in any change in the ClientHello.
- [C] upon receiving a TLS 1.3 HelloRetryRequest that selects an unproposed or TLS 1.2 cipher suite
    - Note that it is not possible to actually negotiate this cipher suite with a subsequent ServerHello
    - RFC 8446 - 4.1.4.  Hello Retry Request
        > Upon receipt of a HelloRetryRequest, the client MUST check the legacy_version, legacy_session_id_echo, cipher_suite, and legacy_compression_method as specified in Section 4.1.3
- [C+S] upon receiving a ChangeCipherSpec message with an invalid content (such as 0x7D) as long as this content consists of one byte
    - RFC 5246 - 7.1 Change Cipher Spec Protocol
        > The message consists of a single byte of value 1.
- [C] when a server chooses a non-CBC cipher suite but negotiates encrypt-then-MAC
    - RFC 7366 - 3. Applying Encrypt-then-MAC
        > If a server receives an encrypt-then-MAC request extension from a client and then selects a stream or Authenticated Encryption with Associated Data (AEAD) ciphersuite, it MUST NOT send an encrypt-then-MAC response extension back to the client.
- [C] upon receiving a GREASE extension as part of a ServerHello, HelloRetryRequest, or EncryptedExtensions message
    - Note that this is likely caused by an unknown extension type, not a specific GREASE value
    - RFC 9701 - 3.1.  Client Behavior
        > In particular, the client MUST fail the connection if a GREASE value appears in any of the following: [...] Any ServerHello extension, [...] Any EncryptedExtensions extension
    - In general a client MUST reject such an extension if it wasn't proposed
- [C] upon receiving a forbidden extension in the EncryptedExtensions message (specifically tested with Padding extension)
    - RFC 8446 - 4.3.1 Encrypted Extensions
        > The client MUST check EncryptedExtensions for the presence of any forbidden extensions and if any are found MUST abort the handshake with an "illegal_parameter" alert.
- [C] upon receiving a ServerHello negotiating TLS 1.3 that does not echo the empty session ID sent by GnuTLS
    - RFC 8446 - 4.1.3 Server Hello
        > A client which receives a legacy_session_id_echo field that does not match what it sent in the ClientHello MUST abort the handshake with an "illegal_parameter" alert.

- [S] upon receiving a Padding extension that contains bytes other than 0x00
    - Please leave a comment if your implementation does not support this extension and hence ignores the content
    - RFC 7685 - 3. Padding Extension
        > The client MUST fill the padding extension completely with zero bytes, although the padding extension_data field may be empty.

- [S] upon receiving a SupportedPointFormat extension 
that only accepts compressed points or an invalid format
    - 8422 -  5.1. Client Hello Extensions
        > If the client sends the extension and the extension does not contain the uncompressed point format, and the client has used the Supported Groups extension to indicate support for any of the curves defined in this specification, then the server MUST abort the handshake and return an illegal_parameter alert.

## Only session closed but no alert sent

- [C] upon receiving a record with an invalid MAC / AEAD tag or with an invalid padding (for CBC cipher suites)

- [C] upon receiving a record without any content

- [C] upon receiving a record that exceeds the maximum ciphertext or plaintext fragment length

- [C] upon receiving an encrypted legacy ChangeCipherSpec message or an unprotected ChangeCipherSpec after a completed handshake in a TLS 1.3 session

## Different alert sent than defined by the RFC
- [S] upon receiving a ClientHello proposing TLS 1.3 without a SignatureAlgorithms extension. GnuTLS sends a 'handshake failure' alert.
    - RFC 8446 - 4.2.3 Signature Algorithms
        > If a server is authenticating via a certificate and the client has not sent a "signature_algorithms" extension, then the server MUST abort the handshake with a "missing_extension" alert (see Section 9.2).

- [C] upon receiving a ServerHello that negotiates TLS 1.3 and selects an unproposed cipher suite. GnuTLS sends a 'handshake failure' alert.
    - RFC 8446 - 4.1.3 Server Hello
        > A client which receives a cipher suite that was not offered MUST abort the handshake with an "illegal_parameter" alert. 

- [C] upon receiving an EncryptedExtensions message that contains a SupportedVersions extension. GnuTLS sends an 'unsupported extension' alert.
    - RFC 8446 - 4.3.1 Encrypted Extensions
        > The client MUST check EncryptedExtensions for the presence of any forbidden extensions and if any are found MUST abort the handshake with an "illegal_parameter" alert.

- [C+S] upon receiving a 'close notify' alert during the handshake. GnuTLS sends an 'internal error'
    - This may be a corner case due to the uncompleted handshake
    - RFC 5246 7.2.1 Closure Alerts
        > The other party MUST respond with a close_notify alert of its own and close down the connection immediately, discarding any pending writes.

- [S] upon receiving a record with the undefined record content type 0xff at the beginning of the handshake, GnuTLS responds with a 'record overflow' alert
    - Note that this may be related to legacy SSL2 parsing code
    - RFC 8446 - 5. Record Protocol
        > If a TLS implementation receives an unexpected record type, it MUST terminate the connection with an "unexpected_message" alert.

Reply to this email directly or view it on GitLab: https://gitlab.com/gnutls/gnutls/-/issues/1247
You're receiving this email because of your account on gitlab.com.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.gnupg.org/pipermail/gnutls-devel/attachments/20210604/3ba6d9c5/attachment-0001.html>

More information about the Gnutls-devel mailing list