Beispiel #1
0
def invalid_certificate_scans_parameters(*args, **kwargs):
    certificate = kwargs["certificate"]
    certificate_scan = kwargs["certificate_scan"]
    protocol = kwargs["protocol"]

    if certificate_scan == CertificateScan.CIPHER_SUITE_SCAN:
        if "openssl-1.0.2" in get_flag(S2N_PROVIDER_VERSION):
            # SSLyze scan results in rejected ciphers that should have been accepted
            # for TLS 1.2
            if protocol == Protocols.TLS12:
                return True
        if "fips" in get_flag(S2N_PROVIDER_VERSION):
            # BUG_IN_SSLYZE / TLS version supported assertion failures for ECDSA scans
            # in SSLv3 and RSA with TLS version < 1.2 with fips libcryptos
            if "ECDSA" in certificate.name and protocol == Protocols.SSLv3:
                return True
            if "RSA" in certificate.name and protocol in [
                    Protocols.SSLv3, Protocols.TLS10, Protocols.TLS11
            ]:
                return True
    elif certificate_scan == CertificateScan.ELLIPTIC_CURVE_SCAN:
        # SSLyze curves scan errors when given ECDSA certs
        if "ECDSA" in certificate.name:
            return True

        # SSLyze curves scan fails to validate with openssl 1.0.2 fips
        if "openssl-1.0.2-fips" in get_flag(S2N_PROVIDER_VERSION):
            return True

    return invalid_test_parameters(*args, **kwargs)
Beispiel #2
0
def test_well_known_endpoints(managed_process, protocol, endpoint, provider,
                              cipher):
    port = "443"

    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host=endpoint,
                                     port=port,
                                     insecure=False,
                                     trust_store=TRUST_STORE_BUNDLE,
                                     protocol=protocol,
                                     cipher=cipher)

    if get_flag(S2N_FIPS_MODE) is True:
        client_options.trust_store = "../integration/trust-store/ca-bundle.trust.crt"
    else:
        client_options.trust_store = "../integration/trust-store/ca-bundle.crt"

    # expect_stderr=True because S2N sometimes receives OCSP responses:
    # https://github.com/aws/s2n-tls/blob/14ed186a13c1ffae7fbb036ed5d2849ce7c17403/bin/echo.c#L180-L184
    client = managed_process(provider,
                             client_options,
                             timeout=5,
                             expect_stderr=True)

    expected_result = EXPECTED_RESULTS.get((endpoint, cipher), None)

    for results in client.get_results():
        results.assert_success()

        if expected_result is not None:
            assert to_bytes(expected_result['cipher']) in results.stdout
            assert to_bytes(expected_result['kem']) in results.stdout
Beispiel #3
0
def test_well_known_endpoints(managed_process, protocol, endpoint, provider,
                              cipher):
    port = "443"

    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host=endpoint,
                                     port=port,
                                     insecure=False,
                                     trust_store=TRUST_STORE_BUNDLE,
                                     protocol=protocol,
                                     cipher=cipher)

    if get_flag(S2N_FIPS_MODE) is True:
        client_options.trust_store = "../integration/trust-store/ca-bundle.trust.crt"
    else:
        client_options.trust_store = "../integration/trust-store/ca-bundle.crt"

    client = managed_process(provider, client_options, timeout=5)

    expected_result = EXPECTED_RESULTS.get((endpoint, cipher), None)

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0

        if expected_result is not None:
            assert bytes(
                expected_result['cipher'].encode('utf-8')) in results.stdout
            assert bytes(
                expected_result['kem'].encode('utf-8')) in results.stdout
Beispiel #4
0
    def setup_client(self):
        """
        Using the passed ProviderOptions, create a command line.
        """
        cmd_line = []
        if self.options.use_mainline_version is True:
            cmd_line.append('s2nc_head')
        else:
            cmd_line.append('s2nc')
        cmd_line.append('--non-blocking')

        # Tests requiring reconnects can't wait on echo data,
        # but all other tests can.
        if self.options.reconnect is not True:
            cmd_line.append('-e')

        if self.options.use_session_ticket is False:
            cmd_line.append('-T')

        if self.options.insecure is True:
            cmd_line.append('--insecure')
        elif self.options.trust_store:
            cmd_line.extend(['-f', self.options.trust_store])
        elif self.options.cert:
            cmd_line.extend(['-f', self.options.cert])

        if self.options.reconnect is True:
            cmd_line.append('-r')

        # If the test provided a cipher (security policy) that is compatible with
        # s2n, we'll use it. Otherwise, default to the appropriate `test_all` policy.
        cipher_prefs = 'test_all_tls12'
        if self.options.protocol is Protocols.TLS13:
            cipher_prefs = 'test_all'
        if self.options.cipher and self.options.cipher.s2n:
            cipher_prefs = self.options.cipher.name

        cmd_line.extend(['-c', cipher_prefs])

        if self.options.use_client_auth:
            if self.options.key:
                cmd_line.extend(['--key', self.options.key])
            if self.options.cert:
                cmd_line.extend(['--cert', self.options.cert])

        if get_flag(S2N_FIPS_MODE):
            cmd_line.append("--enter-fips-mode")

        if self.options.enable_client_ocsp:
            cmd_line.extend(["--status"])

        if self.options.extra_flags is not None:
            cmd_line.extend(self.options.extra_flags)

        cmd_line.extend([self.options.host, self.options.port])

        # Clients are always ready to connect
        self.set_provider_ready()

        return cmd_line
Beispiel #5
0
def test_well_known_endpoints(managed_process, protocol, endpoint):
    port = "443"

    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host=endpoint['endpoint'],
                                     port=port,
                                     insecure=False,
                                     client_trust_store=TRUST_STORE_BUNDLE,
                                     protocol=protocol)

    if get_flag(S2N_FIPS_MODE) is True:
        client_options.client_trust_store = "../integration/trust-store/ca-bundle.trust.crt"
    else:
        client_options.client_trust_store = "../integration/trust-store/ca-bundle.crt"

    if 'cipher_preference_version' in endpoint:
        client_options.cipher = endpoint['cipher_preference_version']

    client = managed_process(S2N, client_options, timeout=5)

    for results in client.get_results():
        if results.exception is not None or results.exit_code != 0:
            assert endpoint['endpoint'] in expected_failures

        if 'expected_cipher' in endpoint:
            assert bytes(
                endpoint['expected_cipher'].encode('utf-8')) in results.stdout
Beispiel #6
0
    def setup_server(self):
        # s2nd prints this message after it begins listening for connections
        self.ready_to_test_marker = 'Listening on'

        """
        Using the passed ProviderOptions, create a command line.
        """
        cmd_line = []
        if self.options.use_mainline_version is True:
            cmd_line.append('s2nd_head')
        else:
            cmd_line.append('s2nd')
        cmd_line.extend(['-X', '--self-service-blinding', '--non-blocking'])

        if self.options.key is not None:
            cmd_line.extend(['--key', self.options.key])
        if self.options.cert is not None:
            cmd_line.extend(['--cert', self.options.cert])

        if self.options.insecure is True:
            cmd_line.append('--insecure')
        elif self.options.trust_store:
            cmd_line.extend(['-t', self.options.trust_store])
        elif self.options.cert:
            cmd_line.extend(['-t', self.options.cert])

        # If the test provided a cipher (security policy) that is compatible with
        # s2n, we'll use it. Otherwise, default to the appropriate `test_all` policy.
        cipher_prefs = 'test_all_tls12'
        if self.options.protocol is Protocols.TLS13:
            cipher_prefs = 'test_all'
        if self.options.cipher and self.options.cipher.s2n:
            cipher_prefs = self.options.cipher.name

        cmd_line.extend(['-c', cipher_prefs])

        if self.options.use_client_auth is True:
            cmd_line.append('-m')

        if self.options.use_session_ticket is False:
            cmd_line.append('-T')

        if self.options.reconnects_before_exit is not None:
            cmd_line.append(
                '--max-conns={}'.format(self.options.reconnects_before_exit))

        if get_flag(S2N_FIPS_MODE):
            cmd_line.append("--enter-fips-mode")

        if self.options.ocsp_response is not None:
            cmd_line.extend(["--ocsp", self.options.ocsp_response])

        if self.options.extra_flags is not None:
            cmd_line.extend(self.options.extra_flags)

        cmd_line.extend([self.options.host, self.options.port])

        return cmd_line
Beispiel #7
0
    def supports_protocol(cls, protocol, with_cert=None):
        # Disable TLS 1.3 tests for all libcryptos that don't support 1.3
        if all([
            libcrypto not in get_flag(S2N_PROVIDER_VERSION)
            for libcrypto in TLS_13_LIBCRYPTOS
        ]) and protocol == Protocols.TLS13:
            return False

        return True
Beispiel #8
0
def invalid_sslyze_scan_parameters(*args, **kwargs):
    scan_command = kwargs["scan_command"]
    protocol = kwargs["protocol"]

    # BUG_IN_SSLYZE error in TLS compression and session renegotiation scans
    # in fips libcryptos when TLS version < 1.3
    if "fips" in get_flag(
            S2N_PROVIDER_VERSION) and protocol != Protocols.TLS13:
        if scan_command in [
                sslyze.ScanCommand.TLS_COMPRESSION,
                sslyze.ScanCommand.SESSION_RENEGOTIATION
        ]:
            return True
    # BUG_IN_SSLYZE error for session resumption scan with openssl 1.0.2 fips
    if "openssl-1.0.2-fips" in get_flag(S2N_PROVIDER_VERSION):
        if scan_command == sslyze.ScanCommand.SESSION_RESUMPTION:
            return True

    return invalid_test_parameters(*args, **kwargs)
Beispiel #9
0
    def supports_cipher(cls, cipher, with_curve=None):
        # Disable chacha20 tests in unsupported libcryptos
        if any([
            libcrypto in get_flag(S2N_PROVIDER_VERSION)
            for libcrypto in [
                "openssl-1.0.2",
                "libressl"
            ]
        ]) and "CHACHA20" in cipher.name:
            return False

        return True
Beispiel #10
0
def test_s2n_client_ocsp_response(managed_process, cipher, provider,
                                  other_provider, curve, protocol,
                                  certificate):
    if "boringssl" in get_flag(S2N_PROVIDER_VERSION):
        pytest.skip("s2n-tls client with boringssl does not support ocsp")

    port = next(available_ports)

    random_bytes = data_bytes(128)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     port=port,
                                     cipher=cipher,
                                     curve=curve,
                                     protocol=protocol,
                                     insecure=True,
                                     data_to_send=random_bytes,
                                     enable_client_ocsp=True)

    server_options = ProviderOptions(
        mode=Provider.ServerMode,
        port=port,
        cipher=cipher,
        curve=curve,
        protocol=protocol,
        key=certificate.key,
        cert=certificate.cert,
        ocsp_response={
            "RSA": TEST_OCSP_DIRECTORY + "ocsp_response.der",
            "EC": TEST_OCSP_DIRECTORY + "ocsp_ecdsa_response.der"
        }.get(certificate.algorithm),
    )

    kill_marker = None

    if provider == GnuTLS:
        kill_marker = random_bytes

    server = managed_process(provider,
                             server_options,
                             timeout=30,
                             kill_marker=kill_marker)
    client = managed_process(S2N, client_options, timeout=30)

    for client_results in client.get_results():
        client_results.assert_success()
        assert b"OCSP response received" in client_results.stdout

    for server_results in server.get_results():
        server_results.assert_success()
        # Avoid debugging information that sometimes gets inserted after the first character.
        assert random_bytes[1:] in server_results.stdout or random_bytes[
            1:] in server_results.stderr
Beispiel #11
0
    def supports_signature(cls, signature):
        # Disable RSA_PSS_RSAE_SHA256 in unsupported libcryptos
        if any([
            libcrypto in get_flag(S2N_PROVIDER_VERSION)
            for libcrypto in [
                "openssl-1.0.2",
                "libressl",
                "boringssl"
            ]
        ]) and signature == Signatures.RSA_PSS_RSAE_SHA256:
            return False

        return True
Beispiel #12
0
def test_s2nc_to_s2nd_pq_handshake(managed_process, protocol, certificate,
                                   client_cipher, server_cipher, provider,
                                   other_provider):
    # Incorrect cipher is negotiated when both ciphers are PQ_TLS_1_0_2020_12 with
    # openssl 1.0.2, boringssl, and libressl libcryptos
    if all([
            client_cipher == Ciphers.PQ_TLS_1_0_2020_12,
            server_cipher == Ciphers.PQ_TLS_1_0_2020_12,
            any([
                libcrypto in get_flag(S2N_PROVIDER_VERSION)
                for libcrypto in ["boringssl", "libressl", "openssl-1.0.2"]
            ])
    ]):
        pytest.skip()

    port = next(available_ports)

    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     port=port,
                                     insecure=True,
                                     cipher=client_cipher,
                                     protocol=protocol)

    server_options = ProviderOptions(mode=Provider.ServerMode,
                                     port=port,
                                     protocol=protocol,
                                     cipher=server_cipher,
                                     cert=certificate.cert,
                                     key=certificate.key)

    server = managed_process(S2N, server_options, timeout=5)
    client = managed_process(S2N, client_options, timeout=5)

    if pq_enabled():
        expected_result = EXPECTED_RESULTS.get((client_cipher, server_cipher),
                                               None)
    else:
        # If PQ is not enabled in s2n, we expect classic handshakes to be negotiated.
        # Leave the expected cipher blank, as there are multiple possibilities - the
        # important thing is that kem and kem_group are NONE.
        expected_result = {"cipher": "", "kem": "NONE", "kem_group": "NONE"}

    # Client and server are both s2n; can make meaningful assertions about negotiation for both
    for results in client.get_results():
        results.assert_success()
        assert_s2n_negotiation_parameters(results, expected_result)

    for results in server.get_results():
        results.assert_success()
        assert_s2n_negotiation_parameters(results, expected_result)
Beispiel #13
0
    def supports_cipher(cls, cipher, with_curve=None):
        if "openssl-1.0.2" in get_flag(S2N_PROVIDER_VERSION) and with_curve is not None:
            invalid_ciphers = [
                Ciphers.ECDHE_RSA_AES128_SHA,
                Ciphers.ECDHE_RSA_AES256_SHA,
                Ciphers.ECDHE_RSA_AES128_SHA256,
                Ciphers.ECDHE_RSA_AES256_SHA384,
                Ciphers.ECDHE_RSA_AES128_GCM_SHA256,
                Ciphers.ECDHE_RSA_AES256_GCM_SHA384,
            ]

            # OpenSSL 1.0.2 and 1.0.2-FIPS can't find a shared cipher with S2N
            # when P-384 is used, but I can't find any reason why.
            if with_curve is Curves.P384 and cipher in invalid_ciphers:
                return False

        return True
Beispiel #14
0
class OpenSSL(Provider):

    _version = get_flag(S2N_PROVIDER_VERSION)

    def __init__(self, options: ProviderOptions):
        self.ready_to_send_input_marker = None
        Provider.__init__(self, options)

    def _join_ciphers(self, ciphers):
        """
        Given a list of ciphers, join the names with a ':' like OpenSSL expects
        """
        assert type(ciphers) is list

        cipher_list = []
        for c in ciphers:
            cipher_list.append(c.name)

        ciphers = ':'.join(cipher_list)

        return ciphers

    def _cipher_to_cmdline(self, cipher):
        cmdline = list()

        ciphers = []
        if type(cipher) is list:
            # In the case of a cipher list we need to be sure TLS13 specific ciphers aren't
            # mixed with ciphers from previous versions
            is_tls13_or_above = (cipher[0].min_version >= Protocols.TLS13)
            mismatch = [
                c for c in cipher
                if (c.min_version >= Protocols.TLS13) != is_tls13_or_above
            ]

            if len(mismatch) > 0:
                raise Exception(
                    "Cannot combine ciphers for TLS1.3 or above with older ciphers: {}"
                    .format([c.name for c in cipher]))

            ciphers.append(self._join_ciphers(cipher))
        else:
            is_tls13_or_above = (cipher.min_version >= Protocols.TLS13)
            ciphers.append(cipher.name)

        if is_tls13_or_above:
            cmdline.append('-ciphersuites')
        else:
            cmdline.append('-cipher')

        return cmdline + ciphers

    @classmethod
    def get_version(cls):
        return cls._version

    @classmethod
    def supports_protocol(cls, protocol, with_cert=None):
        if protocol is Protocols.TLS13:
            if 'openssl-1.1.1' in OpenSSL.get_version():
                return True
            else:
                return False

        return True

    @classmethod
    def supports_cipher(cls, cipher, with_curve=None):
        is_openssl_111 = "openssl-1.1.1" in OpenSSL.get_version()
        if is_openssl_111 and cipher.openssl1_1_1 is False:
            return False

        if not is_openssl_111:
            # OpenSSL 1.0.2 does not have ChaChaPoly
            if 'CHACHA20' in cipher.name:
                return False

        if cipher.fips is False and "fips" in OpenSSL.get_version():
            return False

        if "openssl-1.0.2" in OpenSSL.get_version() and with_curve is not None:
            invalid_ciphers = [
                Ciphers.ECDHE_RSA_AES128_SHA,
                Ciphers.ECDHE_RSA_AES256_SHA,
                Ciphers.ECDHE_RSA_AES128_SHA256,
                Ciphers.ECDHE_RSA_AES256_SHA384,
                Ciphers.ECDHE_RSA_AES128_GCM_SHA256,
                Ciphers.ECDHE_RSA_AES256_GCM_SHA384,
            ]

            # OpenSSL 1.0.2 and 1.0.2-FIPS can't find a shared cipher with S2N
            # when P-384 is used, but I can't find any reason why.
            if with_curve is Curves.P384 and cipher in invalid_ciphers:
                return False

        return True

    def setup_client(self):
        # s_client prints this message before it is ready to send/receive data
        self.ready_to_send_input_marker = 'Verify return code'

        cmd_line = ['openssl', 's_client']
        cmd_line.extend(
            ['-connect', '{}:{}'.format(self.options.host, self.options.port)])

        # Additional debugging that will be captured incase of failure
        cmd_line.extend(['-debug', '-tlsextdebug', '-state'])

        if self.options.key is not None:
            cmd_line.extend(['-key', self.options.key])

        # Unlike s2n, OpenSSL allows us to be much more specific about which TLS
        # protocol to use.
        if self.options.protocol == Protocols.TLS13:
            cmd_line.append('-tls1_3')
        elif self.options.protocol == Protocols.TLS12:
            cmd_line.append('-tls1_2')
        elif self.options.protocol == Protocols.TLS11:
            cmd_line.append('-tls1_1')
        elif self.options.protocol == Protocols.TLS10:
            cmd_line.append('-tls1')

        if self.options.cipher is not None:
            cmd_line.extend(self._cipher_to_cmdline(self.options.cipher))

        if self.options.curve is not None:
            cmd_line.extend(['-curves', str(self.options.curve)])

        if self.options.use_client_auth:
            if self.options.key:
                cmd_line.extend(['-key', self.options.key])
            if self.options.cert:
                cmd_line.extend(['-cert', self.options.cert])

        if self.options.reconnect is True:
            cmd_line.append('-reconnect')

        if self.options.extra_flags is not None:
            cmd_line.extend(self.options.extra_flags)

        if self.options.server_name is not None:
            cmd_line.extend(['-servername', self.options.server_name])
            if self.options.verify_hostname is not None:
                cmd_line.extend(['-verify_hostname', self.options.server_name])

        # Clients are always ready to connect
        self.set_provider_ready()

        return cmd_line

    def setup_server(self):
        # s_server prints this message before it is ready to send/receive data
        self.ready_to_test_marker = 'ACCEPT'

        cmd_line = ['openssl', 's_server']
        cmd_line.extend(['-accept', '{}'.format(self.options.port)])

        if self.options.reconnects_before_exit is not None:
            # If the user request a specific reconnection count, set it here
            cmd_line.extend(
                ['-naccept',
                 str(self.options.reconnects_before_exit)])
        else:
            # Exit after the first connection by default
            cmd_line.extend(['-naccept', '1'])

        # Additional debugging that will be captured incase of failure
        cmd_line.extend(['-debug', '-tlsextdebug', '-state'])

        if self.options.cert is not None:
            cmd_line.extend(['-cert', self.options.cert])
        if self.options.key is not None:
            cmd_line.extend(['-key', self.options.key])

        # Unlike s2n, OpenSSL allows us to be much more specific about which TLS
        # protocol to use.
        if self.options.protocol == Protocols.TLS13:
            cmd_line.append('-tls1_3')
        elif self.options.protocol == Protocols.TLS12:
            cmd_line.append('-tls1_2')
        elif self.options.protocol == Protocols.TLS11:
            cmd_line.append('-tls1_1')
        elif self.options.protocol == Protocols.TLS10:
            cmd_line.append('-tls1')

        if self.options.cipher is not None:
            cmd_line.extend(self._cipher_to_cmdline(self.options.cipher))
            if self.options.cipher.parameters is not None:
                cmd_line.extend(['-dhparam', self.options.cipher.parameters])

        if self.options.curve is not None:
            cmd_line.extend(['-curves', str(self.options.curve)])
        if self.options.use_client_auth is True:
            # We use "Verify" instead of "verify" to require a client cert
            cmd_line.extend(['-Verify', '1'])

        if self.options.extra_flags is not None:
            cmd_line.extend(self.options.extra_flags)

        return cmd_line
Beispiel #15
0
    },
    {
        "endpoint": "s3.amazonaws.com"
    },
    {
        "endpoint": "twitter.com"
    },
    {
        "endpoint": "wikipedia.org"
    },
    {
        "endpoint": "yahoo.com"
    },
]

if get_flag(S2N_NO_PQ, False) is False:
    # If PQ was compiled into S2N, test the PQ preferences against KMS
    pq_endpoints = [{
        "endpoint": "kms.us-east-1.amazonaws.com",
        "cipher_preference_version": Ciphers.KMS_PQ_TLS_1_0_2019_06,
        "expected_cipher": "ECDHE-BIKE-RSA-AES256-GCM-SHA384"
    }, {
        "endpoint": "kms.us-east-1.amazonaws.com",
        "cipher_preference_version": Ciphers.PQ_SIKE_TEST_TLS_1_0_2019_11,
        "expected_cipher": "ECDHE-SIKE-RSA-AES256-GCM-SHA384"
    }]

    ENDPOINTS.extend(pq_endpoints)

# Wikipedia still fails when connecting from the codebuild images
expected_failures = ['wikipedia.org']
Beispiel #16
0
def pq_enabled():
    """
    Returns true or false to indicate whether PQ crypto is enabled in s2n
    """
    return not (get_flag(S2N_NO_PQ, False) or get_flag(S2N_FIPS_MODE, False))
Beispiel #17
0
def invalid_test_parameters(*args, **kwargs):
    """
    Determine if the parameters chosen for a test makes sense.
    This function returns True or False, indicating whether a
    test should be "deselected" based on the arguments.
    """
    protocol = kwargs.get('protocol')
    provider = kwargs.get('provider')
    certificate = kwargs.get('certificate')
    client_certificate = kwargs.get('client_certificate')
    cipher = kwargs.get('cipher')
    curve = kwargs.get('curve')

    # Only TLS1.3 supports RSA-PSS-PSS certificates
    # (Earlier versions support RSA-PSS signatures, just via RSA-PSS-RSAE)
    if protocol and protocol is not Protocols.TLS13:
        if client_certificate and client_certificate.algorithm == 'RSAPSS':
            return True
        if certificate and certificate.algorithm == 'RSAPSS':
            return True

    if provider is not None and not provider.supports_protocol(protocol):
        return True

    if cipher is not None:
        # TODO Remove this check once the pq-enabled update is complete; once complete,
        # s2n will ignore PQ ciphers if PQ is not enabled, so we won't have to perform
        # this check in the tests (See discussion in PR #2426).
        if cipher.pq and (get_flag(S2N_NO_PQ, False)
                          or get_flag(S2N_FIPS_MODE, False)):
            return True

        # If the selected protocol doesn't allow the cipher, don't test
        if protocol is not None:
            if cipher.min_version > protocol:
                return True

            # Ciphersuites prior to TLS13 can not be used with TLS13
            # https://wiki.openssl.org/index.php/TLS1.3#Differences_with_TLS1.2_and_below
            if protocol is Protocols.TLS13 and cipher.min_version < protocol:
                return True

        if provider is not None and not provider.supports_cipher(
                cipher, with_curve=curve):
            return True

    # If we are using a cipher that depends on a specific certificate algorithm
    # deselect the test if the wrong certificate is used.
    if certificate is not None:
        if protocol is not None and provider.supports_protocol(
                protocol, with_cert=certificate) is False:
            return True
        if cipher is not None and certificate.compatible_with_cipher(
                cipher) is False:
            return True

    # If the curve is specified, then all signatures must use that curve
    if curve:
        if certificate and not certificate.compatible_with_curve(curve):
            return True
        if client_certificate and not client_certificate.compatible_with_curve(
                curve):
            return True

    # Prevent situations like using X25519 with TLS1.2
    if curve is not None:
        if protocol is not None and curve.min_protocol > protocol:
            return True

    return False