def test_well_known_endpoints(managed_process, protocol, endpoint, provider, cipher): port = "443" client_options = ProviderOptions(mode=Provider.ClientMode, host=endpoint, port=port, insecure=False, trust_store=TRUST_STORE_BUNDLE, protocol=protocol, cipher=cipher) if get_flag(S2N_FIPS_MODE) is True: client_options.trust_store = "../integration/trust-store/ca-bundle.trust.crt" else: client_options.trust_store = "../integration/trust-store/ca-bundle.crt" client = managed_process(provider, client_options, timeout=5) expected_result = EXPECTED_RESULTS.get((endpoint, cipher), None) for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 if expected_result is not None: assert bytes( expected_result['cipher'].encode('utf-8')) in results.stdout assert bytes( expected_result['kem'].encode('utf-8')) in results.stdout
def test_well_known_endpoints(managed_process, protocol, endpoint): port = "443" client_options = ProviderOptions(mode=Provider.ClientMode, host=endpoint['endpoint'], port=port, insecure=False, client_trust_store=TRUST_STORE_BUNDLE, protocol=protocol) if get_flag(S2N_FIPS_MODE) is True: client_options.client_trust_store = "../integration/trust-store/ca-bundle.trust.crt" else: client_options.client_trust_store = "../integration/trust-store/ca-bundle.crt" if 'cipher_preference_version' in endpoint: client_options.cipher = endpoint['cipher_preference_version'] client = managed_process(S2N, client_options, timeout=5) for results in client.get_results(): if results.exception is not None or results.exit_code != 0: assert endpoint['endpoint'] in expected_failures if 'expected_cipher' in endpoint: assert bytes( endpoint['expected_cipher'].encode('utf-8')) in results.stdout
def test_oqs_openssl_to_s2nd_pq_handshake(managed_process, protocol, cipher, kem_group): # If PQ is not enabled in s2n, there is no reason to test against oqs_openssl if not pq_enabled(): return port = next(available_ports) client_options = ProviderOptions( mode=Provider.ClientMode, port=port, protocol=protocol, env_overrides=get_oqs_openssl_override_env_vars(), extra_flags=['-groups', kem_group.oqs_name]) server_options = ProviderOptions(mode=Provider.ServerMode, port=port, protocol=protocol, cipher=cipher, 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) expected_result = EXPECTED_RESULTS.get((kem_group, cipher), None) for results in client.get_results(): # Client is OQS OpenSSL; just ensure the process exited successfully results.assert_success() for results in server.get_results(): # Server is s2n; can make meaningful assertions about negotiation results.assert_success() assert_s2n_negotiation_parameters(results, expected_result)
def test_well_known_endpoints(managed_process, protocol, endpoint, provider, cipher): port = "443" client_options = ProviderOptions(mode=Provider.ClientMode, host=endpoint, port=port, insecure=False, trust_store=TRUST_STORE_BUNDLE, protocol=protocol, cipher=cipher) if get_flag(S2N_FIPS_MODE) is True: client_options.trust_store = "../integration/trust-store/ca-bundle.trust.crt" else: client_options.trust_store = "../integration/trust-store/ca-bundle.crt" # expect_stderr=True because S2N sometimes receives OCSP responses: # https://github.com/aws/s2n-tls/blob/14ed186a13c1ffae7fbb036ed5d2849ce7c17403/bin/echo.c#L180-L184 client = managed_process(provider, client_options, timeout=5, expect_stderr=True) expected_result = EXPECTED_RESULTS.get((endpoint, cipher), None) for results in client.get_results(): results.assert_success() if expected_result is not None: assert to_bytes(expected_result['cipher']) in results.stdout assert to_bytes(expected_result['kem']) in results.stdout
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() ])
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 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
def test_s2nc_to_s2nd_pq_handshake(managed_process, protocol, certificate, client_cipher, server_cipher, provider, other_provider): # Incorrect cipher is negotiated when both ciphers are PQ_TLS_1_0_2020_12 with # openssl 1.0.2, boringssl, and libressl libcryptos if all([ client_cipher == Ciphers.PQ_TLS_1_0_2020_12, server_cipher == Ciphers.PQ_TLS_1_0_2020_12, any([ libcrypto in get_flag(S2N_PROVIDER_VERSION) for libcrypto in ["boringssl", "libressl", "openssl-1.0.2"] ]) ]): pytest.skip() port = next(available_ports) client_options = ProviderOptions(mode=Provider.ClientMode, port=port, insecure=True, cipher=client_cipher, protocol=protocol) server_options = ProviderOptions(mode=Provider.ServerMode, port=port, protocol=protocol, cipher=server_cipher, cert=certificate.cert, key=certificate.key) server = managed_process(S2N, server_options, timeout=5) client = managed_process(S2N, client_options, timeout=5) if pq_enabled(): expected_result = EXPECTED_RESULTS.get((client_cipher, server_cipher), None) else: # If PQ is not enabled in s2n, we expect classic handshakes to be negotiated. # Leave the expected cipher blank, as there are multiple possibilities - the # important thing is that kem and kem_group are NONE. expected_result = {"cipher": "", "kem": "NONE", "kem_group": "NONE"} # Client and server are both s2n; can make meaningful assertions about negotiation for both for results in client.get_results(): results.assert_success() assert_s2n_negotiation_parameters(results, expected_result) for results in server.get_results(): results.assert_success() assert_s2n_negotiation_parameters(results, expected_result)
def test_s2n_client_with_early_data_rejected_via_hrr(managed_process, tmp_path, cipher, curve, certificate, protocol, provider, other_provider, early_data_size): if provider == S2N: pytest.skip( "S2N does not respect ProviderOptions.curve, so does not trigger a retry" ) early_data_file = str(tmp_path / EARLY_DATA_FILE) early_data = get_early_data_bytes(early_data_file, early_data_size) options = ProviderOptions( port=next(available_ports), cipher=cipher, curve=curve, protocol=protocol, insecure=True, use_session_ticket=True, reconnect=True, ) options.ticket_file = None options.early_data_file = early_data_file options.max_early_data = MAX_EARLY_DATA client_options = copy.copy(options) client_options.mode = Provider.ClientMode server_options = copy.copy(options) server_options.mode = Provider.ServerMode server_options.key = certificate.key # Required for the initial connection server_options.cert = certificate.cert # Required for the initial connection server_options.reconnects_before_exit = NUM_CONNECTIONS server = managed_process(provider, server_options, timeout=10) s2n_client = managed_process(S2N, client_options, timeout=10) for results in s2n_client.get_results(): results.assert_success() assert S2N_EARLY_DATA_MARKER not in results.stdout assert S2N_HRR_MARKER in results.stdout assert results.stdout.count( to_bytes(S2N_EARLY_DATA_REJECTED_MARKER)) == NUM_RESUMES for results in server.get_results(): results.assert_success() assert early_data not in results.stdout
def test_s2n_client_happy_path(managed_process, cipher, curve, provider): host = "localhost" port = next(available_ports) client_options = ProviderOptions( mode="client", host="localhost", port=port, cipher=cipher, insecure=True, tls13=True) server_options = copy.copy(client_options) 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(provider, server_options, timeout=5) client = managed_process(S2N, client_options, timeout=5) # 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 b"Actual protocol version: 34" 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
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 setup_provider_options(mode, port, cipher, curve, certificate, data_to_send, client_psk_params): options = ProviderOptions(host="localhost", port=port, cipher=cipher, curve=curve, insecure=True, protocol=Protocols.TLS13, data_to_send=data_to_send, mode=mode, extra_flags=client_psk_params) if certificate: options.key = certificate.key options.cert = certificate.cert options.trust_store = certificate.cert return options
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_sslyze_certificate_scans(managed_process, protocol, certificate): port = next(available_ports) server_options = ProviderOptions(mode=S2N.ServerMode, host=HOST, port=port, protocol=protocol, key=certificate.key, cert=certificate.cert, insecure=True, extra_flags=["--parallelize"]) server = managed_process(S2N, server_options, timeout=30) scans = [CIPHER_SUITE_SCANS.get(protocol.value)] # sslyze curves scan errors when given ECDSA certs if "ECDSA" not in certificate.name: scans.append(sslyze.ScanCommand.ELLIPTIC_CURVES) scan_attempt_results = run_sslyze_scan(HOST, port, scans) for scan_attempt_result in scan_attempt_results: assert_scan_result_completed(scan_attempt_result) scan_result = scan_attempt_result.scan_result scan_attempts = get_scan_attempts(scan_result) for scan_attempt in scan_attempts: validate_scan_result(scan_attempt, protocol, certificate) server.kill()
def test_sslyze_certificate_scans(managed_process, protocol, certificate, provider, certificate_scan): port = next(available_ports) server_options = ProviderOptions(mode=S2N.ServerMode, host=HOST, port=port, protocol=protocol, key=certificate.key, cert=certificate.cert, insecure=True, extra_flags=["--parallelize"]) server = managed_process(S2N, server_options, timeout=30) scan = { CertificateScan.CIPHER_SUITE_SCAN: CIPHER_SUITE_SCANS.get(protocol.value), CertificateScan.ELLIPTIC_CURVE_SCAN: sslyze.ScanCommand.ELLIPTIC_CURVES }.get(certificate_scan) scan_attempt_results = run_sslyze_scan(HOST, port, [scan]) for scan_attempt_result in scan_attempt_results: assert_scan_result_completed(scan_attempt_result) scan_result = scan_attempt_result.scan_result scan_attempts = get_scan_attempts(scan_result) for scan_attempt in scan_attempts: validate_scan_result(scan_attempt, protocol, certificate) server.kill()
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_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_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_with_early_data_rejected_via_hrr(managed_process, tmp_path, cipher, curve, certificate, protocol, provider, other_provider, early_data_size): ticket_file = str(tmp_path / TICKET_FILE) early_data_file = str(tmp_path / EARLY_DATA_FILE) early_data = get_early_data_bytes(early_data_file, early_data_size) options = ProviderOptions( port=next(available_ports), cipher=cipher, curve=(S2N_UNSUPPORTED_CURVE + ":" + str(curve)), protocol=protocol, insecure=True, use_session_ticket=True, data_to_send=DATA_TO_SEND, ) options.ticket_file = ticket_file options.early_data_file = early_data_file options.max_early_data = MAX_EARLY_DATA get_ticket_from_s2n_server(options, managed_process, provider, certificate) client_options = copy.copy(options) client_options.mode = Provider.ClientMode server_options = copy.copy(options) server_options.mode = Provider.ServerMode s2n_server = managed_process(S2N, server_options, timeout=10) client = managed_process(provider, client_options, timeout=10) for results in client.get_results(): results.assert_success() assert early_data not in results.stdout for results in s2n_server.get_results(): results.assert_success() assert S2N_EARLY_DATA_MARKER not in results.stdout assert S2N_HRR_MARKER in results.stdout assert to_bytes(S2N_EARLY_DATA_RECV_MARKER) not in results.stdout assert to_bytes(S2N_EARLY_DATA_REJECTED_MARKER) in results.stdout assert DATA_TO_SEND in results.stdout
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_new_server_old_ticket(managed_process, tmp_path, cipher, curve, certificate, protocol, provider, other_provider): ticket_file = str(tmp_path / TICKET_FILE) assert not os.path.exists(ticket_file) options = ProviderOptions( port=next(available_ports), cipher=cipher, curve=curve, protocol=protocol, insecure=True, use_session_ticket=True, ) client_options = copy.copy(options) client_options.mode = Provider.ClientMode client_options.extra_flags = ['-sess_out', ticket_file] server_options = copy.copy(options) server_options.mode = Provider.ServerMode server_options.use_mainline_version = True server_options.key = certificate.key server_options.cert = certificate.cert server_options.data_to_send = CLOSE_MARKER_BYTES 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 client.get_results(): results.assert_success() for results in s2n_server.get_results(): results.assert_success() assert os.path.exists(ticket_file) client_options.extra_flags = ['-sess_in', ticket_file] server_options.use_mainline_version = False 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 client.get_results(): results.assert_success() for results in s2n_server.get_results(): results.assert_success() assert S2N_RESUMPTION_MARKER 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_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, 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_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_s2nc_to_s2nd_pq_handshake(managed_process, protocol, client_cipher, server_cipher): host = "localhost" port = next(available_ports) client_options = ProviderOptions(mode=Provider.ClientMode, host=host, port=port, insecure=True, cipher=client_cipher, protocol=protocol) server_options = ProviderOptions(mode=Provider.ServerMode, host=host, port=port, protocol=protocol, cipher=server_cipher, cert=Certificates.RSA_4096_SHA512.cert, key=Certificates.RSA_4096_SHA512.key) server = managed_process(S2N, server_options, timeout=5) client = managed_process(S2N, client_options, timeout=5) if pq_enabled(): expected_result = EXPECTED_RESULTS.get((client_cipher, server_cipher), None) else: # If PQ is not enabled in s2n, we expect classic handshakes to be negotiated. # Leave the expected cipher blank, as there are multiple possibilities - the # important thing is that kem and kem_group are NONE. expected_result = {"cipher": "", "kem": "NONE", "kem_group": "NONE"} # Client and server are both s2n; can make meaningful assertions about negotiation for both for results in client.get_results(): assert results.exception is None assert results.exit_code == 0 assert_s2n_negotiation_parameters(results, expected_result) for results in server.get_results(): assert results.exception is None assert results.exit_code == 0 assert_s2n_negotiation_parameters(results, expected_result)
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
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_s2n_server_with_early_data(managed_process, tmp_path, cipher, curve, protocol, provider, certificate, early_data_size): ticket_file = str(tmp_path / TICKET_FILE) early_data_file = str(tmp_path / EARLY_DATA_FILE) early_data = get_early_data_bytes(early_data_file, early_data_size) options = ProviderOptions( port=next(available_ports), cipher=cipher, curve=curve, protocol=protocol, insecure=True, use_session_ticket=True, data_to_send=DATA_TO_SEND, ) options.ticket_file = ticket_file options.early_data_file = early_data_file options.max_early_data = MAX_EARLY_DATA get_ticket_from_s2n_server(options, managed_process, provider, certificate) client_options = copy.copy(options) client_options.mode = Provider.ClientMode server_options = copy.copy(options) server_options.mode = Provider.ServerMode s2n_server = managed_process(S2N, server_options) client = managed_process(provider, client_options) for results in client.get_results(): results.assert_success() for results in s2n_server.get_results(): results.assert_success() assert S2N_EARLY_DATA_MARKER in results.stdout assert (to_bytes(S2N_EARLY_DATA_RECV_MARKER) + early_data) in results.stdout assert to_bytes(S2N_EARLY_DATA_ACCEPTED_MARKER) in results.stdout assert DATA_TO_SEND in results.stdout