def test_s2n_client_key_update(managed_process, cipher):
    host = "localhost"
    port = next(available_ports)

    update_requested = b"K\n"
    server_data = data_bytes(10)
    client_data = data_bytes(10)
    # Last statement printed out by Openssl after handshake
    starting_marker = "Secure Renegotiation IS supported"
    key_update_marker = "TLSv1.3 write server key update"
    read_key_update_marker = b"TLSv1.3 read client key update"

    send_marker_list = [starting_marker, key_update_marker]

    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        host=host,
        port=port,
        cipher=cipher,
        data_to_send=[client_data],
        insecure=True,
        protocol=Protocols.TLS13,
    )

    server_options = copy.copy(client_options)

    server_options.mode = Provider.ServerMode
    server_options.key = "../pems/ecdsa_p384_pkcs1_key.pem"
    server_options.cert = "../pems/ecdsa_p384_pkcs1_cert.pem"
    server_options.data_to_send = [update_requested, server_data]

    server = managed_process(
        OpenSSL,
        server_options,
        send_marker=send_marker_list,
        close_marker=str(client_data),
        timeout=5,
    )
    client = managed_process(
        S2N,
        client_options,
        send_marker=[str(server_data)],
        close_marker=str(server_data),
        timeout=5,
    )

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

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert read_key_update_marker in results.stderr
        assert client_data in results.stdout
def test_s2n_server_key_update(managed_process, cipher):
    host = "localhost"
    port = next(available_ports)

    update_requested = b"K"
    server_data = data_bytes(10)
    client_data = data_bytes(10)
    starting_marker = "Verify return code"
    key_update_marker = "KEYUPDATE"

    send_marker_list = [starting_marker, key_update_marker]

    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        host=host,
        port=port,
        cipher=cipher,
        data_to_send=[update_requested, client_data],
        insecure=True,
        protocol=Protocols.TLS13,
    )

    server_options = copy.copy(client_options)

    server_options.mode = Provider.ServerMode
    server_options.key = "../pems/ecdsa_p384_pkcs1_key.pem"
    server_options.cert = "../pems/ecdsa_p384_pkcs1_cert.pem"
    server_options.data_to_send = [server_data]

    server = managed_process(S2N,
                             server_options,
                             send_marker=[str(client_data)],
                             timeout=5)
    client = managed_process(
        OpenSSL,
        client_options,
        send_marker=send_marker_list,
        close_marker=str(server_data),
        timeout=5,
    )

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert key_update_marker in str(results.stderr)
        assert server_data in results.stdout

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert client_data in results.stdout
Beispiel #3
0
def test_s2n_server_low_latency(managed_process, multi_cipher, provider,
                                protocol, certificate):
    port = next(available_ports)

    random_bytes = data_bytes(65519)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=multi_cipher,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.extra_flags = ['--prefer-low-latency']
    server_options.key = certificate.key
    server_options.cert = certificate.cert

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

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

    expected_version = get_expected_s2n_version(protocol, provider)

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Actual protocol version: {}".format(
            expected_version).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout
Beispiel #4
0
def test_s2n_server_low_latency(managed_process, multi_cipher, provider, protocol, certificate):
    if provider is OpenSSL and 'openssl-1.0.2' in provider.get_version():
        pytest.skip('{} does not allow setting max fragmentation for packets'.format(provider))

    port = next(available_ports)

    random_bytes = data_bytes(65519)
    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        port=port,
        cipher=multi_cipher,
        data_to_send=random_bytes,
        insecure=True,
        protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.extra_flags = ['--prefer-low-latency']
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.cipher = None

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

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

    expected_version = get_expected_s2n_version(protocol, provider)

    for results in server.get_results():
        results.assert_success()
        assert to_bytes("Actual protocol version: {}".format(expected_version)) in results.stdout
        assert random_bytes in results.stdout
Beispiel #5
0
def get_ticket_from_s2n_server(options, managed_process, provider, certificate):
    port = next(available_ports)

    """
    Generally clients start checking for stdin EoF to exit as soon as they finish the handshake.
    To make sure the client reliably receives the post-handshake NST,
    do NOT indicate stdin EoF until after some data has been received from the server.
    """
    close_marker_bytes = data_bytes(10)

    client_options = copy.copy(options)
    client_options.mode = Provider.ClientMode
    client_options.port = port

    server_options = copy.copy(options)
    server_options.mode = Provider.ServerMode
    server_options.port = port
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.data_to_send = close_marker_bytes

    assert not os.path.exists(options.ticket_file)

    s2n_server = managed_process(
        S2N, server_options, send_marker=S2N.get_send_marker())
    client = managed_process(provider, client_options,
                             close_marker=str(close_marker_bytes))

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

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

    assert os.path.exists(options.ticket_file)
Beispiel #6
0
def test_s2n_server_ocsp_response(managed_process, cipher, provider,
                                  other_provider, curve, protocol,
                                  certificate):
    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,
        insecure=True,
        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:
        # The GnuTLS client hangs for a while after sending. Speed up the tests by killing
        # it immediately after sending the message.
        kill_marker = b"Sent: "

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

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

        assert any([{
            GnuTLS:
            b"OCSP Response Information:\n\tResponse Status: Successful",
            OpenSSL: b"OCSP Response Status: successful"
        }.get(provider) in stream
                    for stream in client_results.output_streams()])

    for server_results in server.get_results():
        server_results.assert_success()
        # Avoid debugging information that sometimes gets inserted after the first character.
        assert any([
            random_bytes[1:] in stream
            for stream in server_results.output_streams()
        ])
Beispiel #7
0
def test_s2n_client_happy_path(managed_process, cipher, provider, curve,
                               protocol, certificate):
    port = next(available_ports)

    # We can only send 4096 - 1 (\n at the end) bytes here because of the
    # way some servers chunk output (when writing to stdout). If we send
    # 8192 bytes, then openssl will print some debugging information in
    # the middle of our chunk. We still want that debugging data in case
    # of a failure, so we just send less data, rather than lose debug
    # information.
    random_bytes = data_bytes(4095)
    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        port=port,
        cipher=cipher,
        curve=curve,
        data_to_send=random_bytes,
        insecure=True,
        protocol=protocol,
    )

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert

    kill_marker = None
    if provider == GnuTLS:
        kill_marker = random_bytes

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(provider,
                             server_options,
                             timeout=5,
                             kill_marker=kill_marker)
    client = managed_process(S2N, client_options, timeout=5)

    expected_version = get_expected_s2n_version(protocol, provider)

    # The client is always S2N in this test, so we can examine
    # the stdout reliably.
    for client_results in client.get_results():
        client_results.assert_success()
        assert to_bytes("Actual protocol version: {}".format(
            expected_version)) in client_results.stdout

    # The server will be one of all supported providers. We
    # just want to make sure there was no exception and that
    # the client exited cleanly.
    for server_results in server.get_results():
        server_results.assert_success()
        # Avoid debugging information that sometimes gets inserted after the first character.
        assert any([
            random_bytes[1:] in stream
            for stream in server_results.output_streams()
        ])
Beispiel #8
0
def test_s2n_client_multiple_psks(managed_process, cipher, curve, protocol,
                                  provider, other_provider, psk_identity,
                                  psk_secret):
    port = next(available_ports)
    random_bytes = data_bytes(10)
    psk_hash_alg = get_psk_hash_alg_from_cipher(cipher)
    skip_invalid_psk_tests(provider, psk_hash_alg)

    client_psk_params = setup_s2n_psk_params(psk_identity, psk_secret,
                                             psk_hash_alg)
    client_psk_params.extend(
        setup_s2n_psk_params(PSK_IDENTITY_NO_MATCH, PSK_SECRET_NO_MATCH,
                             psk_hash_alg))
    client_options = setup_provider_options(S2N.ClientMode, port, cipher,
                                            curve, None, random_bytes,
                                            client_psk_params)

    server_psk_params = []
    if provider == OpenSSL:
        """
        OpenSSL Provider does not support multiple PSKs in the same connection, 
        the last psk params is the final psk used in the connection. 
        """
        server_psk_params.extend(
            setup_openssl_psk_params(PSK_IDENTITY_NO_MATCH_2,
                                     PSK_SECRET_NO_MATCH_2))
        server_psk_params.extend(
            setup_openssl_psk_params(psk_identity, psk_secret))
        server_psk_params += ['-nocert']
    else:
        server_psk_params.extend(
            setup_s2n_psk_params(PSK_IDENTITY_NO_MATCH_2,
                                 PSK_SECRET_NO_MATCH_2, psk_hash_alg))
        server_psk_params.extend(
            setup_s2n_psk_params(psk_identity, psk_secret, psk_hash_alg))
    server_options = setup_provider_options(provider.ServerMode, port, cipher,
                                            curve, None, None,
                                            server_psk_params)

    server = managed_process(provider,
                             server_options,
                             timeout=5,
                             close_marker=str(random_bytes))
    client = managed_process(S2N, client_options, timeout=5)

    for results in client.get_results():
        results.assert_success()
        validate_negotiated_psk_s2n(Outcome.psk_connection, psk_identity,
                                    results)

    for results in server.get_results():
        results.assert_success()
        if provider == S2N:
            validate_negotiated_psk_s2n(Outcome.psk_connection, psk_identity,
                                        results)
        else:
            validate_negotiated_psk_openssl(Outcome.psk_connection, results)
        assert random_bytes in results.stdout
def test_s2n_client_signature_algorithms(managed_process, cipher, provider,
                                         protocol, certificate, signature,
                                         client_auth):
    port = next(available_ports)

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     use_client_auth=client_auth,
                                     key=certificate.key,
                                     cert=certificate.cert,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.trust_store = certificate.cert
    server_options.extra_flags = ['-sigalgs', signature.name]

    if client_auth is True:
        client_options.trust_store = Certificates.RSA_2048_SHA256_WILDCARD.cert
        server_options.key = Certificates.RSA_2048_SHA256_WILDCARD.key
        server_options.cert = Certificates.RSA_2048_SHA256_WILDCARD.cert

        if signature.sig_type == 'RSA-PSS':
            client_options.trust_store = Certificates.RSA_PSS_2048_SHA256.cert
            server_options.key = Certificates.RSA_PSS_2048_SHA256.key
            server_options.cert = Certificates.RSA_PSS_2048_SHA256.cert
        elif signature.sig_type == 'ECDSA':
            client_options.trust_store = Certificates.ECDSA_256.cert
            server_options.key = Certificates.ECDSA_256.key
            server_options.cert = Certificates.ECDSA_256.cert

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

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes('Shared Signature Algorithms: {}+{}'.format(
            signature.sig_type,
            signature.sig_digest).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout

    expected_version = get_expected_s2n_version(protocol, provider)

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Actual protocol version: {}".format(
            expected_version).encode('utf-8')) in results.stdout
Beispiel #10
0
def test_s2nd_tls13_negotiates_tls12(managed_process, cipher, curve, protocol,
                                     provider, certificate):
    port = next(available_ports)

    random_bytes = data_bytes(24)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     curve=curve,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.protocol = Protocols.TLS13

    # Allow the server to use all ciphers, don't limit to TLS13 even though we are
    # forcing the protocol to be TLS13
    server_options.extra_flags = ['-c', 'test_all']

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

    server_version = get_expected_s2n_version(Protocols.TLS13, provider)
    actual_version = get_expected_s2n_version(protocol, provider)

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        if provider is S2N:
            # The client will get the server version from the SERVER HELLO, which will be the negotiated version
            assert bytes("Server protocol version: {}".format(
                actual_version).encode('utf-8')) in results.stdout
            assert bytes("Actual protocol version: {}".format(
                actual_version).encode('utf-8')) in results.stdout
        elif provider is OpenSSL:
            # This check cares about other providers because we want to know that they did negotiate the version
            # that our S2N server intended to negotiate.
            openssl_version = get_expected_openssl_version(protocol)
            assert bytes("Protocol  : {}".format(openssl_version).encode(
                'utf-8')) in results.stdout

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Server protocol version: {}".format(
            server_version).encode('utf-8')) in results.stdout
        assert bytes("Actual protocol version: {}".format(
            actual_version).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout
Beispiel #11
0
def test_s2nc_tls13_negotiates_tls12(managed_process, cipher, curve,
                                     certificate, protocol, provider,
                                     other_provider):
    port = next(available_ports)

    random_bytes = data_bytes(24)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     port=port,
                                     cipher=cipher,
                                     curve=curve,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     protocol=Protocols.TLS13)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.protocol = protocol

    kill_marker = None
    if provider == GnuTLS:
        kill_marker = random_bytes

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

    client_version = get_expected_s2n_version(Protocols.TLS13, provider)
    actual_version = get_expected_s2n_version(protocol, provider)

    for results in client.get_results():
        results.assert_success()
        assert to_bytes("Client protocol version: {}".format(
            client_version)) in results.stdout
        assert to_bytes("Actual protocol version: {}".format(
            actual_version)) in results.stdout

    for results in server.get_results():
        results.assert_success()
        if provider is S2N:
            # The server is only TLS12, so it reads the version from the CLIENT_HELLO, which is never above TLS12
            # This check only cares about S2N. Trying to maintain expected output of other providers doesn't
            # add benefit to whether the S2N client was able to negotiate a lower TLS version.
            assert to_bytes("Client protocol version: {}".format(
                actual_version)) in results.stdout
            assert to_bytes("Actual protocol version: {}".format(
                actual_version)) in results.stdout

        assert any([
            random_bytes[1:] in stream for stream in results.output_streams()
        ])
Beispiel #12
0
def test_hrr_with_s2n_as_server(managed_process, cipher, provider, curve,
                                protocol, certificate):
    port = next(available_ports)

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        host="localhost",
        port=port,
        cipher=cipher,
        data_to_send=random_bytes,
        insecure=True,
        curve=curve,
        extra_flags=['-msg', '-curves', 'X448:' + str(curve)],
        protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.extra_flags = None

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(S2N, server_options, timeout=5)
    client = managed_process(provider, client_options, timeout=5)

    # The client should connect and return without error
    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert random_bytes in results.stdout
        assert bytes("Curve: {}".format(
            CURVE_NAMES[curve.name]).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout

    client_hello_count = 0
    server_hello_count = 0
    finished_count = 0
    # HRR random data Refer: https://tools.ietf.org/html/rfc8446#section-4.1.3
    marker = b"cf 21 ad 74 e5 9a 61 11 be 1d"

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert marker in results.stdout
        client_hello_count = results.stdout.count(b'ClientHello')
        server_hello_count = results.stdout.count(b'ServerHello')
        finished_count = results.stdout.count(b'Finished')

    assert client_hello_count == 2
    assert server_hello_count == 2
    assert finished_count == 2
Beispiel #13
0
def test_s2nd_tls13_negotiates_tls12(managed_process, cipher, curve,
                                     certificate, protocol, provider,
                                     other_provider):
    port = next(available_ports)

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

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    # When the protocol is set to TLS13, the s2n server provider will default to using
    # all ciphers, not just the TLS13 ciphers. This is the desired behavior for this test.
    server_options.protocol = Protocols.TLS13

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

    server_version = get_expected_s2n_version(Protocols.TLS13, provider)
    actual_version = get_expected_s2n_version(protocol, provider)

    for results in client.get_results():
        results.assert_success()
        if provider is S2N:
            # The client will get the server version from the SERVER HELLO, which will be the negotiated version
            assert to_bytes("Server protocol version: {}".format(
                actual_version)) in results.stdout
            assert to_bytes("Actual protocol version: {}".format(
                actual_version)) in results.stdout
        elif provider is OpenSSL:
            # This check cares about other providers because we want to know that they did negotiate the version
            # that our S2N server intended to negotiate.
            openssl_version = get_expected_openssl_version(protocol)
            assert to_bytes(
                "Protocol  : {}".format(openssl_version)) in results.stdout
        elif provider is GnuTLS:
            gnutls_version = get_expected_gnutls_version(protocol)
            assert to_bytes(f"Version: {gnutls_version}") in results.stdout

    for results in server.get_results():
        results.assert_success()
        assert (to_bytes("Server protocol version: {}".format(server_version))
                in results.stdout)
        assert (to_bytes("Actual protocol version: {}".format(actual_version))
                in results.stdout)
        assert random_bytes[1:] in results.stdout
Beispiel #14
0
def test_client_auth_with_s2n_client_with_cert(managed_process, cipher, curve,
                                               protocol, provider,
                                               certificate):
    port = next(available_ports)

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        host="localhost",
        port=port,
        cipher=cipher,
        curve=curve,
        data_to_send=random_bytes,
        use_client_auth=True,
        client_key_file=certificate.key,
        client_certificate_file=certificate.cert,
        client_trust_store=Certificates.RSA_2048_SHA256_WILDCARD.cert,
        insecure=False,
        protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = Certificates.RSA_2048_SHA256_WILDCARD.key
    server_options.cert = Certificates.RSA_2048_SHA256_WILDCARD.cert

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(provider, server_options, timeout=5)
    client = managed_process(S2N, client_options, timeout=5)

    # The client should connect and return without error
    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0

    # Openssl should indicate the procotol version in a successful connection.
    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert random_bytes in results.stdout

        if protocol is Protocols.TLS13:
            message = bytes(
                "SSL_accept:SSLv3/TLS read client certificate\nSSL_accept:SSLv3/TLS read certificate verify\nSSL_accept:SSLv3/TLS read finished"
                .encode('utf-8'))
        else:
            message = bytes(
                'SSL_accept:SSLv3/TLS read client certificate\nSSL_accept:SSLv3/TLS read client key exchange\nSSL_accept:SSLv3/TLS read certificate verify\nSSL_accept:SSLv3/TLS read change cipher spec\nSSL_accept:SSLv3/TLS read finished'
                .encode('utf-8'))

        assert message in results.stderr
Beispiel #15
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 #16
0
def test_s2n_server_happy_path(managed_process, cipher, provider, curve,
                               protocol, certificate):
    port = next(available_ports)

    # s2nd can receive large amounts of data because all the data is
    # echo'd to stdout unmodified. This lets us compare received to
    # expected easily.
    # We purposefully send a non block aligned number to make sure
    # nothing blocks waiting for more data.
    random_bytes = data_bytes(65519)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     cert=certificate,
                                     curve=curve,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(S2N, server_options, timeout=5)
    client = managed_process(provider, client_options, timeout=5)

    # The client will be one of all supported providers. We
    # just want to make sure there was no exception and that
    # the client exited cleanly.
    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0

    expected_version = get_expected_s2n_version(protocol, provider)

    # The server is always S2N in this test, so we can examine
    # the stdout reliably.
    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Actual protocol version: {}".format(
            expected_version).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout

        if provider is not S2N:
            assert bytes("Cipher negotiated: {}".format(
                cipher.name).encode('utf-8')) in results.stdout
Beispiel #17
0
def test_s2nc_tls13_negotiates_tls12(managed_process, cipher, curve, protocol,
                                     provider, certificate):
    port = next(available_ports)

    random_bytes = data_bytes(24)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     curve=curve,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     protocol=Protocols.TLS13)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.protocol = protocol

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

    client_version = get_expected_s2n_version(Protocols.TLS13, provider)
    actual_version = get_expected_s2n_version(protocol, provider)

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Client protocol version: {}".format(
            client_version).encode('utf-8')) in results.stdout
        assert bytes("Actual protocol version: {}".format(
            actual_version).encode('utf-8')) in results.stdout

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        if provider is S2N:
            # The server is only TLS12, so it reads the version from the CLIENT_HELLO, which is never above TLS12
            # This check only cares about S2N. Trying to maintain expected output of other providers doesn't
            # add benefit to whether the S2N client was able to negotiate a lower TLS version.
            assert bytes("Client protocol version: {}".format(
                actual_version).encode('utf-8')) in results.stdout
            assert bytes("Actual protocol version: {}".format(
                actual_version).encode('utf-8')) in results.stdout

        assert random_bytes in results.stdout
Beispiel #18
0
def test_hrr_with_s2n_as_client(managed_process, cipher, provider, curve,
                                protocol, certificate, keyshare):
    port = next(available_ports)

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     curve=curve,
                                     extra_flags=keyshare,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.extra_flags = None
    server_options.curve = Curves.X25519

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(provider, server_options, timeout=5)
    client = managed_process(S2N, client_options, timeout=5)

    # The client should connect and return without error
    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes(
            "Curve: {}".format("x25519").encode('utf-8')) in results.stdout

    marker_part1 = b"cf 21 ad 74 e5"
    marker_part2 = b"9a 61 11 be 1d"

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert marker_part1 in results.stdout and marker_part2 in results.stdout
        if 'none' in keyshare:
            assert b'"key share" (id=51), len=2\n0000 - 00 00' in results.stdout
        assert b'Supported Elliptic Groups: X25519:P-256:P-384' in results.stdout
        assert bytes("Shared Elliptic groups: {}".format(
            server_options.curve).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout
Beispiel #19
0
def test_s2n_client_happy_path(managed_process, cipher, provider, curve,
                               protocol, certificate):
    port = next(available_ports)

    # We can only send 4096 bytes here because of the way some servers chunk
    # output (when writing to stdout). If we send 8192 bytes, then openssl
    # will print some debugging information in the middle of our chunk.
    # We still want that debugging data in case of a failure, so we just
    # send less data, rather than lose debug information.
    random_bytes = data_bytes(4096)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     curve=curve,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(provider, server_options, timeout=5)
    client = managed_process(S2N, client_options, timeout=5)

    expected_version = get_expected_s2n_version(protocol, provider)

    # The client is always S2N in this test, so we can examine
    # the stdout reliably.
    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Actual protocol version: {}".format(
            expected_version).encode('utf-8')) in results.stdout

    # The server will be one of all supported providers. We
    # just want to make sure there was no exception and that
    # the client exited cleanly.
    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        # Avoid debugging information that sometimes gets inserted after the first character
        assert random_bytes[1:] in results.stdout
def test_s2n_client_dynamic_record(custom_mtu, managed_process, cipher, curve,
                                   provider, protocol, certificate):
    host = "localhost"
    port = next(available_ports)

    # 16384 bytes is enough to reliably get a packet that will exceed the MTU
    bytes_to_send = data_bytes(16384)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=bytes_to_send,
                                     insecure=True,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert

    expected_version = get_expected_s2n_version(protocol, provider)

    # This test shouldn't last longer than 5 seconds, even though
    # Tcpdump tends to take a second to startup.
    tcpdump = managed_process(Tcpdump, client_options, timeout=5)
    server = managed_process(provider, server_options, timeout=5)
    client = managed_process(S2N, client_options, timeout=5)

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Actual protocol version: {}".format(
            expected_version).encode('utf-8')) in results.stdout

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

    # The Tcpdump provider only captures 12 packets. This is enough
    # to detect a packet larger than the MTU, but less than the
    # total packets sent. This is important because it lets Tcpdump
    # exit cleanly, which means all the output is available for us
    # to examine.
    for results in tcpdump.get_results():
        assert results.exit_code == 0
        assert find_fragmented_packet(results.stdout) is True
def test_client_auth_with_s2n_server(managed_process, cipher, provider,
                                     protocol, certificate,
                                     client_certificate):
    port = next(available_ports)

    if protocol < Protocols.TLS12 and client_certificate.algorithm == 'EC':
        pytest.xfail(
            "Client auth with ECDSA certs is currently broken for versions < TLS1.2"
        )

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=random_bytes,
                                     use_client_auth=True,
                                     key=client_certificate.key,
                                     cert=client_certificate.cert,
                                     trust_store=certificate.cert,
                                     insecure=False,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.trust_store = client_certificate.cert

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

    # Openssl should send a client certificate and complete the handshake
    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert b'write client certificate' in results.stderr
        assert b'write certificate verify' in results.stderr
        assert_openssl_handshake_complete(results)

    # S2N should successfully connect
    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert_s2n_handshake_complete(results, protocol, provider)
        assert random_bytes in results.stdout
def test_s2n_client_signature_algorithms(managed_process, cipher, provider, protocol, certificate, signature, client_auth):
    port = next(available_ports)

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        port=port,
        cipher=cipher,
        data_to_send=random_bytes,
        insecure=True,
        use_client_auth=client_auth,
        key=certificate.key,
        cert=certificate.cert,
        protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.trust_store = certificate.cert
    server_options.extra_flags=['-sigalgs', signature.name]

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

    for results in server.get_results():
        results.assert_success()
        assert random_bytes in results.stdout

    expected_version = get_expected_s2n_version(protocol, provider)

    # In versions before TLS1.3, the server uses the negotiated signature scheme for the
    # ServerKeyExchange message. The server only sends the ServerKeyExchange message when using
    # a key exchange method that provides forward secrecy, ie, NOT static RSA.
    # So if using RSA key exchange, there is no actual "negotiated" signature scheme, because
    # the server never sends the client a signature scheme.
    #
    # This mostly has to be inferred from the RFCs, but this blog post is a pretty good summary
    # of the situation: https://timtaubert.de/blog/2016/07/the-evolution-of-signatures-in-tls/
    server_sigalg_used = not cipher.iana_standard_name.startswith("TLS_RSA_WITH_")

    for results in client.get_results():
        results.assert_success()
        assert to_bytes("Actual protocol version: {}".format(expected_version)) in results.stdout
        assert signature_marker(Provider.ServerMode, signature) in results.stdout or not server_sigalg_used
        assert (signature_marker(Provider.ClientMode, signature) in results.stdout) == client_auth
Beispiel #23
0
def test_client_auth_with_s2n_server(managed_process, cipher, provider, curve, protocol, certificate):
    host = "localhost"
    port = next(available_ports)

    # NOTE: Client Auth is failing for ECDSA client certs
    if 'ecdsa' in certificate.cert:
        pytest.skip("Skipping known failure, ECDSA client auth certificate")

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(
        mode=Provider.ClientMode,
        host="localhost",
        port=port,
        cipher=cipher,
        curve=curve,
        data_to_send=random_bytes,
        use_client_auth=True,
        client_key_file=certificate.key,
        client_certificate_file=certificate.cert,
        insecure=False,
        protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = "../pems/rsa_2048_sha256_wildcard_key.pem"
    server_options.cert = "../pems/rsa_2048_sha256_wildcard_cert.pem"

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(S2N, server_options, timeout=5)
    client = managed_process(provider, client_options, timeout=5)

    # The client should connect and return without error
    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0

    expected_version = get_expected_s2n_version(protocol, provider)

    # S2N should indicate the procotol version in a successful connection.
    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Actual protocol version: {}".format(expected_version).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout
Beispiel #24
0
def test_s2n_server_framented_data(managed_process, cipher, provider,
                                   other_provider, protocol, certificate,
                                   frag_len):
    if provider is OpenSSL and 'openssl-1.0.2' in provider.get_version():
        pytest.skip(
            '{} does not allow setting max fragmentation for packets'.format(
                provider))

    port = next(available_ports)

    random_bytes = data_bytes(65519)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     record_size=frag_len,
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.extra_flags = None
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.cipher = None

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

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

    expected_version = get_expected_s2n_version(protocol, provider)

    for server_results in server.get_results():
        server_results.assert_success()
        assert to_bytes("Actual protocol version: {}".format(
            expected_version)) in server_results.stdout

        if provider == GnuTLS:
            # GnuTLS ignores data sent through stdin past frag_len up to the application data
            # packet length of 4096. so, just check to make sure data up to frag_len was received.
            assert random_bytes[:frag_len] in server_results.stdout
        else:
            assert random_bytes in server_results.stdout
def test_hrr_with_s2n_as_client(managed_process, cipher, provider, curve,
                                protocol, certificate):
    if curve == S2N_DEFAULT_CURVE:
        pytest.skip("No retry if server curve matches client curve")

    port = next(available_ports)

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

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert
    server_options.extra_flags = None
    server_options.curve = curve

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(provider, server_options, timeout=5)
    client = managed_process(S2N, client_options, timeout=5)

    # The client should connect and return without error
    for results in client.get_results():
        results.assert_success()
        assert to_bytes("Curve: {}".format(
            CURVE_NAMES[curve.name])) in results.stdout
        assert S2N_HRR_MARKER in results.stdout

    marker_part1 = b"cf 21 ad 74 e5"
    marker_part2 = b"9a 61 11 be 1d"

    for results in server.get_results():
        results.assert_success()
        assert marker_part1 in results.stdout and marker_part2 in results.stdout
        assert b'Supported Elliptic Groups: X25519:P-256:P-384' in results.stdout
        assert to_bytes("Shared Elliptic groups: {}".format(
            server_options.curve)) in results.stdout
        assert random_bytes in results.stdout
def test_s2n_server_signature_algorithms(managed_process, cipher, provider,
                                         protocol, certificate, signature,
                                         client_auth):
    port = next(available_ports)

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=random_bytes,
                                     insecure=False,
                                     use_client_auth=client_auth,
                                     key=certificate.key,
                                     cert=certificate.cert,
                                     signature_algorithm=signature,
                                     protocol=protocol)

    if provider == GnuTLS:
        # GnuTLS fails the CA verification. It must be run with this check disabled.
        client_options.extra_flags = ["--no-ca-verification"]

    server_options = copy.copy(client_options)
    server_options.extra_flags = None
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert

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

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

    expected_version = get_expected_s2n_version(protocol, provider)

    for results in server.get_results():
        results.assert_success()
        assert to_bytes("Actual protocol version: {}".format(
            expected_version)) in results.stdout
        assert signature_marker(Provider.ServerMode,
                                signature) in results.stdout
        assert (signature_marker(Provider.ClientMode, signature)
                in results.stdout) == client_auth
        assert random_bytes in results.stdout
def test_s2n_server_signature_algorithms(managed_process, cipher, provider,
                                         protocol, certificate, signature,
                                         client_auth):
    port = next(available_ports)

    random_bytes = data_bytes(64)
    client_options = ProviderOptions(mode=Provider.ClientMode,
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=random_bytes,
                                     insecure=False,
                                     use_client_auth=client_auth,
                                     key=certificate.key,
                                     cert=certificate.cert,
                                     extra_flags=['-sigalgs', signature.name],
                                     protocol=protocol)

    server_options = copy.copy(client_options)
    server_options.extra_flags = None
    server_options.data_to_send = None
    server_options.mode = Provider.ServerMode
    server_options.key = certificate.key
    server_options.cert = certificate.cert

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

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes('Peer signing digest: {}'.format(
            signature.sig_digest).encode('utf-8')) in results.stdout
        assert bytes('Peer signature type: {}'.format(
            signature.sig_type).encode('utf-8')) in results.stdout

    expected_version = get_expected_s2n_version(protocol, provider)

    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert bytes("Actual protocol version: {}".format(
            expected_version).encode('utf-8')) in results.stdout
        assert random_bytes in results.stdout
Beispiel #28
0
def test_s2n_server_happy_path(managed_process, cipher, curve, provider):
    host = "localhost"
    port = next(available_ports)

    # s2nd can receive large amounts of data because all the data is
    # echo'd to stdout unmodified. This lets us compare received to
    # expected easily.
    # The downside here is that, should the test fail, all 4 mbs will
    # be dumped in the exception.
    random_bytes = data_bytes(4194304)
    client_options = ProviderOptions(mode="client",
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     curve=curve,
                                     data_to_send=random_bytes,
                                     insecure=True,
                                     tls13=True)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = "server"
    server_options.key = "../pems/ecdsa_p384_pkcs1_key.pem"
    server_options.cert = "../pems/ecdsa_p384_pkcs1_cert.pem"

    # Passing the type of client and server as a parameter will
    # allow us to use a fixture to enumerate all possibilities.
    server = managed_process(S2N, server_options, timeout=5)
    client = managed_process(provider, client_options, timeout=5)

    # The client will be one of all supported providers. We
    # just want to make sure there was no exception and that
    # the client exited cleanly.
    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0

    # The server is always S2N in this test, so we can examine
    # the stdout reliably.
    for results in server.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert b"Actual protocol version: 34" in results.stdout
        assert random_bytes in results.stdout
Beispiel #29
0
def test_s2n_client_psk_connection(managed_process, cipher, curve, protocol,
                                   provider, other_provider, psk_identity,
                                   psk_secret):
    port = next(available_ports)
    random_bytes = data_bytes(10)
    psk_hash_alg = get_psk_hash_alg_from_cipher(cipher)
    skip_invalid_psk_tests(provider, psk_hash_alg)

    client_psk_params = setup_s2n_psk_params(psk_identity, psk_secret,
                                             psk_hash_alg)
    client_options = setup_provider_options(S2N.ClientMode, port, cipher,
                                            curve, None, random_bytes,
                                            client_psk_params)

    if provider == S2N:
        server_psk_params = setup_s2n_psk_params(psk_identity, psk_secret,
                                                 psk_hash_alg)
    else:
        server_psk_params = setup_openssl_psk_params(psk_identity, psk_secret)
        server_psk_params += ['-nocert']
    server_options = setup_provider_options(provider.ServerMode, port, cipher,
                                            curve, None, None,
                                            server_psk_params)

    server = managed_process(provider,
                             server_options,
                             timeout=5,
                             close_marker=str(random_bytes))
    client = managed_process(S2N, client_options, timeout=5)

    for results in client.get_results():
        results.assert_success()
        validate_negotiated_psk_s2n(Outcome.psk_connection, psk_identity,
                                    results)

    for results in server.get_results():
        results.assert_success()
        if provider == S2N:
            validate_negotiated_psk_s2n(Outcome.psk_connection, psk_identity,
                                        results)
        else:
            validate_negotiated_psk_openssl(Outcome.psk_connection, results)
        assert random_bytes in results.stdout
def test_s2n_client_dynamic_record(custom_mtu, managed_process, cipher, curve):
    host = "localhost"
    port = next(available_ports)

    # 16384 bytes is enough to reliably get a packet that will exceed the MTU
    bytes_to_send = data_bytes(16384)
    client_options = ProviderOptions(mode="client",
                                     host="localhost",
                                     port=port,
                                     cipher=cipher,
                                     data_to_send=bytes_to_send,
                                     insecure=True,
                                     tls13=True)

    server_options = copy.copy(client_options)
    server_options.data_to_send = None
    server_options.mode = "server"
    server_options.key = "../pems/ecdsa_p384_pkcs1_key.pem"
    server_options.cert = "../pems/ecdsa_p384_pkcs1_cert.pem"

    # This test shouldn't last longer than 5 seconds, even though
    # Tcpdump tends to take a second to startup.
    tcpdump = managed_process(Tcpdump, client_options, timeout=5)
    server = managed_process(OpenSSL, server_options, timeout=5)
    client = managed_process(S2N, client_options, timeout=5)

    for results in client.get_results():
        assert results.exception is None
        assert results.exit_code == 0
        assert b"Actual protocol version: 34" in results.stdout

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

    # The Tcpdump provider only captures 12 packets. This is enough
    # to detect a packet larger than the MTU, but less than the
    # total packets sent. This is important because it lets Tcpdump
    # exit cleanly, which means all the output is available for us
    # to examine.
    for results in tcpdump.get_results():
        assert results.exit_code == 0
        assert find_fragmented_packet(results.stdout) is True