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
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() ])
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
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
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
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
def test_tls13_session_resumption_s2n_client(managed_process, cipher, curve, protocol, provider, certificate): port = str(next(available_ports)) # The reconnect option for s2nc allows the client to reconnect automatically # five times. In this test we expect one full connection and five resumption # connections. num_full_connections = 1 num_resumed_connections = 5 client_options = ProviderOptions(mode=Provider.ClientMode, host="localhost", port=port, cipher=cipher, curve=curve, insecure=True, use_session_ticket=True, reconnect=True, protocol=protocol) server_options = copy.copy(client_options) server_options.mode = Provider.ServerMode server_options.key = certificate.key server_options.cert = certificate.cert server_options.reconnects_before_exit = num_resumed_connections + num_full_connections server = managed_process(provider, server_options, timeout=5) client = managed_process(S2N, client_options, timeout=5) s2n_version = get_expected_s2n_version(protocol, provider) # s2nc indicates the number of resumed connections in its output for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 assert not results.stderr assert results.stdout.count( b'Resumed session') == num_resumed_connections assert bytes("Actual protocol version: {}".format(s2n_version).encode( 'utf-8')) in results.stdout server_accepts_str = str(num_resumed_connections + num_full_connections ) + " server accepts that finished" for results in server.get_results(): assert results.exception is None assert results.exit_code == 0 if provider is S2N: assert not results.stderr assert results.stdout.count( b'Resumed session') == num_resumed_connections assert bytes("Actual protocol version: {}".format( s2n_version).encode('utf-8')) in results.stdout else: assert bytes(server_accepts_str.encode('utf-8')) in results.stdout # s_server only writes one certificate message in all of the connections assert results.stderr.count( b'SSL_accept:SSLv3/TLS write certificate' ) == num_full_connections
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() ])
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
def assert_s2n_handshake_complete(results, protocol, provider, is_complete=True): expected_version = get_expected_s2n_version(protocol, provider) if is_complete: assert to_bytes("Actual protocol version: {}".format( expected_version)) in results.stdout else: assert to_bytes("Actual protocol version: {}".format( expected_version)) not in results.stdout
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
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_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
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_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_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
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
def test_oqs_openssl_as_client(managed_process, vector): host = "localhost" port = next(available_ports) # We are manually passing the cipher flag to s2nc and s2nd. # This is because PQ ciphers are specific to S2N at this point # in time. client_options = ProviderOptions( mode=Provider.ClientMode, host=host, port=port, insecure=True, cipher=vector['client_ciphers'], protocol=Protocols.TLS12, env_overrides=get_oqs_openssl_override_env_vars()) server_options = ProviderOptions(mode=Provider.ServerMode, host=host, port=port, cipher=vector['server_ciphers'], protocol=Protocols.TLS12, cert=Certificates.RSA_4096_SHA512.cert, key=Certificates.RSA_4096_SHA512.key) server = managed_process(S2N, server_options, timeout=5) client = managed_process(OpenSSL, client_options, timeout=5) # OQS OpenSSL is Client, so just check that it had a valid exit code for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 expected_version = get_expected_s2n_version(Protocols.TLS12, S2N) # Validate S2N Server results were what was expected 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 bytes("KEM: {}".format( vector['expected_kem']).encode('utf-8')) in results.stdout assert bytes("Cipher negotiated: {}".format( vector['expected_cipher']).encode('utf-8')) in results.stdout
def test_s2n_server_framented_data(managed_process, multi_cipher, provider, protocol, frag_len, 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, host="localhost", port=port, cipher=multi_cipher, data_to_send=random_bytes, insecure=True, extra_flags=['-max_send_frag', str(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 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
def test_sni_match(managed_process, provider, protocol, cert_test_case): host = "localhost" port = next(available_ports) client_options = ProviderOptions(mode=Provider.ClientMode, host=host, port=port, insecure=False, verify_hostname=True, server_name=cert_test_case.client_sni, cipher=cert_test_case.client_ciphers, protocol=protocol) server_options = ProviderOptions(mode=Provider.ServerMode, host=host, port=port, extra_flags=[], protocol=protocol) # Setup the certificate chain for S2ND based on the multicert test case cert_key_list = [(cert[0], cert[1]) for cert in cert_test_case.server_certs] for cert_key_path in cert_key_list: server_options.extra_flags.extend(['--cert', cert_key_path[0]]) server_options.extra_flags.extend(['--key', cert_key_path[1]]) 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 if cert_test_case.client_sni is not None: assert bytes("Server name: {}".format( cert_test_case.client_sni).encode('utf-8')) in results.stdout
def test_session_resumption_s2n_server(managed_process, cipher, curve, protocol, provider, certificate, use_ticket): host = "localhost" port = next(available_ports) client_options = ProviderOptions(mode=Provider.ClientMode, host="localhost", port=port, cipher=cipher, curve=curve, insecure=True, reconnect=True, protocol=protocol) server_options = copy.copy(client_options) server_options.reconnects_before_exit = 6 server_options.mode = Provider.ServerMode server_options.use_session_ticket = use_ticket, 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 should connect and return without error for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 assert results.stdout.count(bytes("Session-ID:".encode('utf-8'))) == 6 expected_version = get_expected_s2n_version(protocol, OpenSSL) # 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 results.stdout.count( bytes("Actual protocol version: {}".format( expected_version).encode('utf-8'))) == 6
def test_pq_handshake(managed_process, vector): host = "localhost" port = next(available_ports) # We are manually passing the cipher flag to s2nc and s2nd. # This is because PQ ciphers are specific to S2N at this point # in time. client_options = ProviderOptions( mode=Provider.ClientMode, host=host, port=port, insecure=True, cipher=None, extra_flags=['--ciphers', vector['client_ciphers'].name], protocol=Protocols.TLS12) server_options = ProviderOptions( mode=Provider.ServerMode, host=host, port=port, cipher=None, extra_flags=['--ciphers', vector['server_ciphers'].name], protocol=Protocols.TLS12) server = managed_process(S2N, 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 expected_version = get_expected_s2n_version(Protocols.TLS12, S2N) 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 bytes("KEM: {}".format( vector['expected_kem']).encode('utf-8')) in results.stdout assert bytes("Cipher negotiated: {}".format( vector['expected_cipher']).encode('utf-8')) in results.stdout
def test_session_resumption_s2n_client(managed_process, cipher, curve, protocol, provider, certificate, use_ticket): port = next(available_ports) client_options = ProviderOptions(mode=Provider.ClientMode, port=port, cipher=cipher, curve=curve, insecure=True, reconnect=True, use_session_ticket=use_ticket, protocol=protocol) server_options = copy.copy(client_options) server_options.reconnects_before_exit = 6 server_options.mode = Provider.ServerMode server_options.key = certificate.key server_options.cert = certificate.cert server_options.use_session_ticket = False # 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, OpenSSL) for results in client.get_results(): results.assert_success() assert results.stdout.count( to_bytes( "Actual protocol version: {}".format(expected_version))) == 6 for results in server.get_results(): results.assert_success() assert results.stdout.count(to_bytes("6 server accepts that finished"))
def test_tls13_session_resumption_s2n_server(managed_process, tmp_path, cipher, curve, protocol, provider, certificate): port = str(next(available_ports)) # Use temp directory to store session tickets p = tmp_path / 'ticket.pem' path_to_ticket = str(p) client_options = ProviderOptions(mode=Provider.ClientMode, host="localhost", port=port, cipher=cipher, curve=curve, insecure=True, reconnect=False, data_to_send=data_bytes(4069), extra_flags=['-sess_out', path_to_ticket], protocol=protocol) server_options = copy.copy(client_options) server_options.mode = Provider.ServerMode server_options.key = certificate.key server_options.cert = certificate.cert server_options.use_session_ticket = True server_options.extra_flags = None server = managed_process(S2N, server_options, timeout=5) client = managed_process(provider, client_options, timeout=5) # The client should have received a session ticket for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 assert b'Post-Handshake New Session Ticket arrived:' in results.stdout for results in server.get_results(): assert results.exception is None assert results.exit_code == 0 # The first connection is a full handshake assert b'Resumed session' not in results.stdout # Client inputs received session ticket to resume a session assert os.path.exists(path_to_ticket) client_options.extra_flags = ['-sess_in', path_to_ticket] port = str(next(available_ports)) client_options.port = port server_options.port = port server = managed_process(S2N, server_options, timeout=5) client = managed_process(provider, client_options, timeout=5) s2n_version = get_expected_s2n_version(protocol, provider) # Client has not read server certificate message as this is a resumed session for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 assert bytes("SSL_connect:SSLv3/TLS read server certificate".encode( 'utf-8')) not in results.stderr # The server should indicate a session has been resumed for results in server.get_results(): assert results.exception is None assert results.exit_code == 0 assert not results.stderr assert b'Resumed session' in results.stdout assert bytes("Actual protocol version: {}".format(s2n_version).encode( 'utf-8')) in results.stdout
def test_s2nd_falls_back_to_full_connection(managed_process, tmp_path, cipher, curve, protocol, provider, certificate): port = str(next(available_ports)) # Use temp directory to store session tickets p = tmp_path / 'ticket.pem' path_to_ticket = str(p) """ This test will set up a full connection with an Openssl client and server to obtain a valid Openssl session ticket. Then, the Openssl client attempts to send the received session ticket to an s2n server to resume a session. s2nd will fallback to a full connection as it does not recognize the session ticket. """ client_options = ProviderOptions(mode=Provider.ClientMode, host="localhost", port=port, cipher=cipher, curve=curve, insecure=True, reconnect=False, extra_flags=['-sess_out', path_to_ticket], data_to_send=data_bytes(4069), protocol=protocol) server_options = copy.copy(client_options) server_options.mode = Provider.ServerMode server_options.key = certificate.key server_options.cert = certificate.cert server_options.extra_flags = None server = managed_process(provider, server_options, timeout=5) client = managed_process(provider, client_options, timeout=5) # The client should have received a session ticket for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 assert b'Post-Handshake New Session Ticket arrived:' in results.stdout for results in server.get_results(): assert results.exception is None assert results.exit_code == 0 # Server should have sent certificate message as this is a full connection assert b'SSL_accept:SSLv3/TLS write certificate' in results.stderr # Client inputs received session ticket to resume a session assert os.path.exists(path_to_ticket) client_options.extra_flags = ['-sess_in', path_to_ticket] port = str(next(available_ports)) client_options.port = port server_options.port = port # Switch providers so now s2n is the server server = managed_process(S2N, server_options, timeout=5) client = managed_process(provider, client_options, timeout=5) s2n_version = get_expected_s2n_version(protocol, provider) # Client has read server certificate because this is a full connection for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 assert bytes("SSL_connect:SSLv3/TLS read server certificate".encode( 'utf-8')) in results.stderr # The server should indicate a session has not been resumed for results in server.get_results(): assert results.exception is None assert not results.stderr assert results.exit_code == 0 assert b'Resumed session' not in results.stdout assert bytes("Actual protocol version: {}".format(s2n_version).encode( 'utf-8')) in results.stdout