From 9dafb48d881218b4cb0ca59ea38eab47d23a6bde Mon Sep 17 00:00:00 2001 From: George Pantelakis Date: Tue, 15 Oct 2024 19:54:21 +0200 Subject: [PATCH] test-tls13-client-certificate-compression.py fix Added a test for empty compressed certificate message body and changed the hardcoded fuzzer from 0 to 1 length --- .github/workflows/ci.yml | 4 +- requirements.txt | 2 +- ...st-tls13-client-certificate-compression.py | 64 +++++++++++++++++-- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 40cd3167..a0da605e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -314,9 +314,9 @@ jobs: - name: Install dependencies (2.6) if: ${{ matrix.python-version == '2.6' }} run: | - wget https://files.pythonhosted.org/packages/f3/3a/6043279b330fd897aa480eafd7f2b92a5a0a2db4f9bfd0b44dc510e17a2b/tlslite-ng-0.8.0b3.tar.gz + wget https://files.pythonhosted.org/packages/5d/6a/7820cbbb9ffd8d6e348726e1ac30687353a026bf3410f00c48f63bc1aea6/tlslite-ng-0.8.0b4.tar.gz wget https://files.pythonhosted.org/packages/b4/4c/f8b4ed6c61dff52294f98aaf99053dd979c1b4233d953f371afb0a2977a1/ecdsa-0.18.0b2-py2.py3-none-any.whl - pip install tlslite-ng-0.8.0b3.tar.gz ecdsa-0.18.0b2-py2.py3-none-any.whl + pip install tlslite-ng-0.8.0b4.tar.gz ecdsa-0.18.0b2-py2.py3-none-any.whl - name: Install dependencies if: ${{ matrix.python-version != '2.6' }} run: pip install -r requirements.txt diff --git a/requirements.txt b/requirements.txt index cbea91aa..ecb86f64 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1 @@ -tlslite-ng==0.8.0-beta3 +tlslite-ng==0.8.0-beta4 diff --git a/scripts/test-tls13-client-certificate-compression.py b/scripts/test-tls13-client-certificate-compression.py index aa8b9068..43711c3e 100644 --- a/scripts/test-tls13-client-certificate-compression.py +++ b/scripts/test-tls13-client-certificate-compression.py @@ -41,7 +41,7 @@ from tlslite.x509certchain import X509CertChain -version = 1 +version = 2 KNOWN_ALGORITHMS = ('zlib', 'brotli', 'zstd') KNOWN_ALGORITHM_CODES = set([ @@ -477,6 +477,62 @@ def main(): node.next_sibling = ExpectClose() conversations["Send empty certificate"] = conversation + # Empty compressed message + conversation = Connect(host, port) + node = conversation + ext = {} + groups = [GroupName.secp256r1] + key_shares = [] + for group in groups: + key_shares.append(key_share_gen(group)) + ext[ExtensionType.key_share] = \ + ClientKeyShareExtension().create(key_shares) + ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ + .create([TLS_1_3_DRAFT, (3, 3)]) + ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ + .create(groups) + sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, + SignatureScheme.rsa_pss_pss_sha256, + SignatureScheme.ecdsa_secp256r1_sha256, + SignatureScheme.ed25519, + SignatureScheme.ed448] + ext[ExtensionType.signature_algorithms] = \ + SignatureAlgorithmsExtension().create(sig_algs) + ext[ExtensionType.signature_algorithms_cert] = \ + SignatureAlgorithmsCertExtension().create(SIG_ALL) + compression_algs = [algorithm] + ext[ExtensionType.compress_certificate] = \ + CompressedCertificateExtension().create(compression_algs) + ext = dict_update_non_present(ext, ext_spec['CH']) + node = node.add_child(ClientHelloGenerator( + ciphers + [CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV], + extensions=ext)) + ext = dict_update_non_present(None, ext_spec['SH']) + node = node.add_child(ExpectServerHello(extensions=ext)) + node = node.add_child(ExpectChangeCipherSpec()) + node = node.add_child(ExpectEncryptedExtensions()) + node = node.add_child(ExpectCertificateRequest()) + node = node.add_child(ExpectCompressedCertificate( + compression_algo=algorithm)) + node.next_sibling = ExpectCertificate() + sibling_node = node.next_sibling + node = node.add_child(ExpectCertificateVerify()) + sibling_node.add_child(node) + node = node.add_child(ExpectFinished()) + node = node.add_child(CompressedCertificateGenerator( + certs=X509CertChain([cert]), + algorithm=CertificateCompressionAlgorithm.zlib, + compressed_certificate_message=bytearray(0), + # Change the decompressed size to max sp the implementation + # will allocate the maximum size possible. If the big data + # comes we will see if there will be a leak or it will break. + uncompressed_message_size=2**12 - 1)) + node = node.add_child(CertificateVerifyGenerator(private_key)) + node = node.add_child(ExpectAlert(AlertLevel.fatal, + AlertDescription.decode_error)) + node.next_sibling = ExpectClose() + conversations["Empty compressed message"] = conversation + # messing with uncompressed_size for name, size in [ ('wrong', 10), ('zero', 0), ('max', 2**24 - 1) @@ -792,7 +848,7 @@ def main(): # Change the decompressed size to max sp the implementation # will allocate the maximum size possible. If the big data # comes we will see if there will be a leak or it will break. - uncompressed_message_size=2**24 - 1)) + uncompressed_message_size=2**12 - 1)) node = node.add_child(CertificateVerifyGenerator(private_key)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_certificate)) @@ -889,7 +945,7 @@ def main(): max_size = 2**24 - 1 - 2 - 3 - 3 if fuzzing_sample_size > 2: sizes = sample(range(1, max_size), fuzzing_sample_size - 2) - sizes.append(0) + sizes.append(1) sizes.append(max_size) for size in sizes: @@ -941,7 +997,7 @@ def main(): # Change the decompressed size to max sp the implementation # will allocate the maximum size possible. If the big data # comes we will see if there will be a leak or it will break. - uncompressed_message_size=2**24 - 1)) + uncompressed_message_size=2**12 - 1)) node = node.add_child(CertificateVerifyGenerator(private_key)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_certificate))