From 9ee84a19d1b84ce543bc3d1b6789886c32f6dea2 Mon Sep 17 00:00:00 2001 From: gpotter2 <10530980+gpotter2@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:01:40 +0100 Subject: [PATCH] Hack support for terrible RSA key-lengths in cryptography 43.0 (#4290) --- scapy/layers/tls/cert.py | 45 ++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/scapy/layers/tls/cert.py b/scapy/layers/tls/cert.py index ed934e8b17f..24f1a6aa437 100644 --- a/scapy/layers/tls/cert.py +++ b/scapy/layers/tls/cert.py @@ -44,12 +44,27 @@ from scapy.layers.tls.crypto.pkcs1 import pkcs_os2ip, _get_hash, \ _EncryptAndVerifyRSA, _DecryptAndSignRSA from scapy.compat import raw, bytes_encode + if conf.crypto_valid: from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import rsa, ec + # cryptography raised the minimum RSA key length to 1024 in 43.0+ + # https://github.com/pyca/cryptography/pull/10278 + # but we need still 512 for EXPORT40 ciphers (yes EXPORT is terrible) + # https://datatracker.ietf.org/doc/html/rfc2246#autoid-66 + # The following detects the change and hacks around it using the backend + + try: + rsa.generate_private_key(public_exponent=65537, key_size=512) + _RSA_512_SUPPORTED = True + except ValueError: + # cryptography > 43.0 + _RSA_512_SUPPORTED = False + from cryptography.hazmat.primitives.asymmetric.rsa import rust_openssl + # Maximum allowed size in bytes for a certificate file, to avoid # loading huge file when importing a cert @@ -263,9 +278,18 @@ def fill_and_store(self, modulus=None, modulusLen=None, pubExp=None): pubExp = pubExp or 65537 if not modulus: real_modulusLen = modulusLen or 2048 - private_key = rsa.generate_private_key(public_exponent=pubExp, - key_size=real_modulusLen, - backend=default_backend()) + if real_modulusLen < 1024 and not _RSA_512_SUPPORTED: + # cryptography > 43.0 compatibility + private_key = rust_openssl.rsa.generate_private_key( + public_exponent=pubExp, + key_size=real_modulusLen, + ) + else: + private_key = rsa.generate_private_key( + public_exponent=pubExp, + key_size=real_modulusLen, + backend=default_backend(), + ) self.pubkey = private_key.public_key() else: real_modulusLen = len(binrepr(modulus)) @@ -470,9 +494,18 @@ def fill_and_store(self, modulus=None, modulusLen=None, pubExp=None, # in order to call RSAPrivateNumbers(...) # if one of these is missing, we generate a whole new key real_modulusLen = modulusLen or 2048 - self.key = rsa.generate_private_key(public_exponent=pubExp, - key_size=real_modulusLen, - backend=default_backend()) + if real_modulusLen < 1024 and not _RSA_512_SUPPORTED: + # cryptography > 43.0 compatibility + self.key = rust_openssl.rsa.generate_private_key( + public_exponent=pubExp, + key_size=real_modulusLen, + ) + else: + self.key = rsa.generate_private_key( + public_exponent=pubExp, + key_size=real_modulusLen, + backend=default_backend(), + ) self.pubkey = self.key.public_key() else: real_modulusLen = len(binrepr(modulus))