Repository navigation
test_ssl.test_shared_ciphers fails when OpenSSL 4.0 enables the TLS 1.3 SM4 cipher suites #159391
Description
Bug report
Summary
OpenSSL 4.0 officially supports the RFC 8998 TLS 1.3 cipher suites TLS_SM4_GCM_SM3 and TLS_SM4_CCM_SM3. Therefore, a test that assumes a fixed set of TLS 1.3 shared cipher suites can fail with a standard upstream OpenSSL build when those suites are available.
Reproduction
# OpenSSL 4.0.2, private prefix
./Configure linux-x86_64 shared --prefix="$OSSL4" --openssldir="$OSSL4/ssl"
make -j"$(nproc)" && make install_sw
test -d "$OSSL4/lib64" && ln -sfn lib64 "$OSSL4/lib"
# Config enabling the SM4 TLS 1.3 suites
cat > openssl-sm4.cnf <<'EOF'
openssl_conf = openssl_init
[openssl_init]
ssl_conf = ssl_sect
[ssl_sect]
system_default = system_default_sect
[system_default_sect]
Ciphersuites = TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:TLS_SM4_GCM_SM3:TLS_SM4_CCM_SM3
EOF
# CPython 3.14.7. The CPPFLAGS are needed only so that _ssl can be imported:
# without them, the build fails with "undefined symbol: TLSv1_method" against OpenSSL 4.0.
export PKG_CONFIG_PATH="$OSSL4/lib/pkgconfig"
export CPPFLAGS='-DOPENSSL_NO_SSL3 -DOPENSSL_NO_TLS1_METHOD -DOPENSSL_NO_TLS1_1_METHOD -DOPENSSL_NO_TLS1_2_METHOD'
./configure --with-openssl="$OSSL4" --with-openssl-rpath=auto --with-pydebug
make -j"$(nproc)"
OPENSSL_CONF="$PWD/openssl-sm4.cnf" ./python -m test test_ssl -v -m test_shared_ciphersPython sees the SM4 suites when the config is loaded:
import ssl
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
for c in ctx.get_ciphers():
if c["protocol"] == "TLSv1.3":
print(c["name"], c["protocol"], c["strength_bits"])TLS_AES_256_GCM_SHA384 TLSv1.3 256
TLS_CHACHA20_POLY1305_SHA256 TLSv1.3 256
TLS_AES_128_GCM_SHA256 TLSv1.3 128
TLS_SM4_GCM_SM3 TLSv1.3 128
TLS_SM4_CCM_SM3 TLSv1.3 128
Result
test_ssl: testing with 'OpenSSL 4.0.2 25 Aug 2026' (4, 0, 0, 2, 0)
test_shared_ciphers (test.test_ssl.ThreadedTests.test_shared_ciphers) ... server: new connection from ('127.0.0.1', 59010)
server: connection cipher is now ('TLS_AES_256_GCM_SHA384', 'TLSv1.3', 256)
FAIL
======================================================================
FAIL: test_shared_ciphers (test.test_ssl.ThreadedTests.test_shared_ciphers)
----------------------------------------------------------------------
Traceback (most recent call last):
File "Lib/test/test_ssl.py", line 4531, in test_shared_ciphers
self.fail(name)
~~~~~~~~~^^^^^^
AssertionError: TLS_SM4_GCM_SM3
----------------------------------------------------------------------
Ran 1 test in 0.077s
FAILED (failures=1)
▎test_shared_ciphers() checks the result of SSLSocket.shared_ciphers(), which returns the ciphers present in both the server's list (SSL_get_ciphers()) and the client's list (SSL_get_client_ciphers()). The test restricts the pre-TLS 1.3 ciphers with SSLContext.set_ciphers(), but TLS 1.3 suites are not controlled by set_ciphers(). For those, the test accepts only names containing the substrings "TLS_AES" or "TLS_CHACHA20". The result therefore depends on which TLS 1.3 suites the OpenSSL build and configuration enable. In the failing run both sides load the same configuration, so TLS_SM4_GCM_SM3 is legitimately in the shared list. shared_ciphers() returns a correct result, and the test rejects it only because of the suite name.
CPython versions tested on:
3.14
Operating systems tested on:
Linux
Activity