Skip to content

[Bug]: RFC 5246 violation in DoClientHello when HAVE_TLS_EXTENSION is undefined #9377

@GSoJC234

Description

@GSoJC234

Contact Details

thkighie1224@postech.ac.kr

Version

v5.8.2-stable

Description

Hello wolfSSL team,

I found an RFC 5246 violation in the function DoClientHello.

When the wolfSSL build is configured without the HAVE_TLS_EXTENSIONS definition,
the following code is executed instead of calling the TLSX_Parse function:

                while (totalExtSz) {
                    word16 extId, extSz;

                    if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz) {
                        ret = BUFFER_ERROR;
                        goto out;
                    }

                    ato16(&input[i], &extId);
                    i += OPAQUE16_LEN;
                    ato16(&input[i], &extSz);
                    i += OPAQUE16_LEN;

                    if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz) {
                        ret = BUFFER_ERROR;
                        goto out;
                    }

                    if (extId == HELLO_EXT_SIG_ALGO) {
                        word16 hashSigAlgoSz;

                        ato16(&input[i], &hashSigAlgoSz);
                        i += OPAQUE16_LEN;

                        if (OPAQUE16_LEN + hashSigAlgoSz > extSz) {
                            ret = BUFFER_ERROR;
                            goto out;
                        }

                        if (hashSigAlgoSz % 2 != 0) {
                            ret = BUFFER_ERROR;
                            goto out;
                        }

                        ssl->clSuites->hashSigAlgoSz = hashSigAlgoSz;
                        if (ssl->clSuites->hashSigAlgoSz >
                                WOLFSSL_MAX_SIGALGO) {
                            WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, "
                                                                  "truncating");
                            ssl->clSuites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO;
                        }

                        XMEMCPY(ssl->clSuites->hashSigAlgo, &input[i],
                                                  ssl->clSuites->hashSigAlgoSz);

                        i += hashSigAlgoSz;
                    }
#ifdef HAVE_EXTENDED_MASTER
                    else if (extId == HELLO_EXT_EXTMS)
                        ssl->options.haveEMS = 1;
#endif
                    else
                        i += extSz;

                    totalExtSz -= (word16)(OPAQUE16_LEN + OPAQUE16_LEN) + extSz;
                }

Unlike TLSX_Parse, which properly checks for duplicate extensions,
the above code does not perform any duplicate-extension validation.

This behavior violates RFC 5246, which explicitly states:
| There MUST NOT be more than one extension of the same type.

Although this issue only occurs when the HAVE_TLS_EXTENSIONS definition is undefined, it still represents a meaningful protocol compliance problem.
Accepting duplicate extensions violates RFC 5246 and could lead to unexpected behavior or interoperability issues with standards-compliant clients and servers.
Therefore, it would be advisable to ensure consistent duplicate-extension checks regardless of build configuration.

Thank you for your time and for maintaining such a great project.

Best regards,
Jaehun Lee

Reproduction steps

  1. ./configure --enable-debug --enable-usersettings --disable-examples
  2. make install
  3. examples/server/server -p 4433 -v 3 -l TLS_RSA_WITH_AES_256_CBC_SHA256
  4. executes below code using python3

user_settings.h

#undef HAVE_TLS_EXTENSIONS

#define WC_NO_HARDEN
#define HAVE_ECC
#define HAVE_ALL_CURVES
#define WOLFSSL_TLS12
#define WOLFSSL_ALT_CERT_CHAINS
#define DEBUG_WOLFSSL
#define DEBUG_WOLFSSL_VERBOSE
#define OPENSSL_EXTRA

#define HAVE_AESGCM
#define HAVE_AESCCM
#define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
#define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256

#define WC_RSA_PSS
#define WOLFSSL_TLS12
#define WOLFSSL_SHA256
#define WOLFSSL_SHA384
#define WOLFSSL_SHA512
#undef WOLFSSL_MD5
#undef WOLFSSL_MD5_SHA

python script

import socket
import binascii

def send_hex_to_server():
    hex_data = (
   "16 03 03 00 3f 01 00 00 3b 03 03 f4 9b 8d ef 1b"
   "fb 8c 4a 34 64 41 15 c3 93 de f7 2a 0d aa 70 12"
   "5e 67 c0 f2 f5 2a e4 6d 75 ec 50 00 00 02 00 3d"
   "01 00 00 10 00 0d 00 04 00 02 08 04 00 0d 00 04"
   "00 02 08 04"
    )
    data = binascii.unhexlify(hex_data.replace(" ", ""))
    with socket.create_connection(("127.0.0.1", 4433)) as sock:
        sock.sendall(data)
        try:
            while True:
                response = sock.recv(4096)
                if not response:
                    print("Connection closed")
                    break
                print("Received: (hex):", response.hex())
        except KeyboardInterrupt:
            print("End")

if __name__ == "__main__":
    send_hex_to_server()

Relevant log output

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions