def main(): if len(sys.argv) < 3: print(usage()) return -1 conversations = {} # 16 chars: POLY1305 tag 128 bit # Tampering one bit suffices to damage the mac # The payload has to be long enough to trigger heap overflow n = 15000 fuzzes = [(-1, 1)] for pos, val in fuzzes: conversation = Connect(sys.argv[1], int(sys.argv[2])) node = conversation ciphers = [CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(fuzz_encrypted_message( ApplicationDataGenerator(b"GET / HTTP/1.0\n" + n * b"A" + b"\n\n"), xors={pos:val})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["XOR position " + str(pos) + " with " + str(hex(val))] = \ conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] #print(conversation_name + "...") runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """Test if server supports the DHE_RSA key exchange""" conversations = {} conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType. renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType. renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity check DHE_RSA_AES_128"] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def test_run_with_expect_and_closed_socket(self): node = ExpectClose() runner = Runner(node) runner.state.msg_sock = mock.MagicMock() runner.state.msg_sock.recvMessageBlocking = \ mock.MagicMock(side_effect=TLSAbruptCloseError()) runner.run()
def main(): # # Test if server aborts connection upon receiving applicaiton data # before Finished # conversations = {} conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=None)) node = node.add_child(ExpectServerHello()) node = node.add_child(Close()) conversations["no extensions"] = conversation conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={})) node = node.add_child(ExpectServerHello()) node = node.add_child(Close()) conversations["empty extensions"] = conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] runner = Runner(conversation) print(str(conversation_name) + "...\n") res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 else: bad += 1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def test_run_with_generate_and_expected_closed_socket(self): node = ClientHelloGenerator() node.next_sibling = ExpectClose() runner = Runner(node) runner.state.msg_sock = mock.MagicMock() runner.state.msg_sock.sendMessageBlocking = \ mock.MagicMock(side_effect=socket.error) # does NOT raise exception runner.run()
def test_run_with_unknown_type(self): node = mock.MagicMock() node.is_command = mock.Mock(return_value=False) node.is_expect = mock.Mock(return_value=False) node.is_generator = mock.Mock(return_value=False) node.child = None runner = Runner(node) with self.assertRaises(AssertionError): runner.run()
def test_run_with_command_node(self): node = mock.MagicMock() node.is_command = mock.Mock(return_value=True) node.is_expect = mock.Mock(return_value=False) node.is_generator = mock.Mock(return_value=False) node.child = None runner = Runner(node) runner.run() node.process.assert_called_once_with(runner.state)
def test_run_with_generate_and_unexpected_closed_socket(self): node = mock.MagicMock() node.is_command = mock.Mock(return_value=False) node.is_expect = mock.Mock(return_value=False) node.is_generator = mock.Mock(return_value=True) node.child = None runner = Runner(node) runner.state.msg_sock = mock.MagicMock() runner.state.msg_sock.sendMessageBlocking = \ mock.MagicMock(side_effect=socket.error) with self.assertRaises(AssertionError): runner.run()
def main(): # # Test if client hello with invalid session ID gets rejected # conversations = {} conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, session_id=bytearray(b'\x03'*33))) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations['33 byte long session id'] = conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] print(str(conversation_name) + "...\n") runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): fingerprint = Scanner().scan(ip="127.0.0.1", port=4433) generator = Generator(fingerprint) good = 0 bad = 0 for conversation in generator: fuzzer = Fuzzer(conversation, fingerprint) for fuzzed in fuzzer: runner = Runner(fuzzed) try: res = runner.run() except: print(traceback.format_exc()) res = False if res: good+=1 else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def test_run_with_generator_node(self): node = mock.MagicMock() node.is_command = mock.Mock(return_value=False) node.is_expect = mock.Mock(return_value=False) node.is_generator = mock.Mock(return_value=True) node.child = None runner = Runner(node) runner.state.msg_sock = mock.MagicMock() runner.run() node.generate.assert_called_once_with(runner.state) self.assertTrue(runner.state.msg_sock.sendMessageBlocking.called) node.post_send.assert_called_once_with(runner.state)
def main(): conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(b"hello server!\n"))) #node = node.add_child(ExpectApplicationData(bytearray(b"hello client!\n"))) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() # run the conversation good = 0 bad = 0 runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): # # Test if server aborts connection upon receiving a hello request # conversations = {} conversation = Connect("localhost", 4433) node = conversation # type - 0, and 3 bytes of length (0) node = node.add_child(RawMessageGenerator(22, bytearray(b'\x00\x00\x00\x00'))) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["hello request to server"] = conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] runner = Runner(conversation) print(str(conversation_name) + "...\n") res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def test_run_with_expect_node_and_unexpected_message(self): node = mock.MagicMock() node.is_command = mock.Mock(return_value=False) node.is_expect = mock.Mock(return_value=True) node.is_generator = mock.Mock(return_value=False) node.get_all_siblings = mock.Mock(return_value=[node]) node.is_match = mock.Mock(return_value=False) node.child = None runner = Runner(node) runner.state.msg_sock = mock.MagicMock() msg = (mock.MagicMock(name="header"), mock.MagicMock(name="parsser")) runner.state.msg_sock.recvMessageBlocking = \ mock.MagicMock(return_value=msg) with self.assertRaises(AssertionError): runner.run() runner.state.msg_sock.sock.close.called_once_with()
def test_run_with_expect_node(self): node = mock.MagicMock() node.is_command = mock.Mock(return_value=False) node.is_expect = mock.Mock(return_value=True) node.is_generator = mock.Mock(return_value=False) node.get_all_siblings = mock.Mock(return_value=[node]) node.is_match = mock.Mock(return_value=True) node.child = None runner = Runner(node) runner.state.msg_sock = mock.MagicMock() msg = (mock.MagicMock(name="header"), mock.MagicMock(name="parser")) runner.state.msg_sock.recvMessageBlocking = mock.Mock(return_value=msg) runner.run() internal_message = messages.Message(msg[0].type, msg[1].bytes) node.is_match.called_once_with(internal_message) node.process.called_once_with(runner.state, internal_message)
def main(): host = "localhost" port = 4433 run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.client_hello_padding: PaddingExtension().create(10)} node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # try large padding extension for ClientHello conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] # lowest size, that causes OpenSSL 1.1.0 and 1.1.0a to crash (SIGSEGV) padding_len = 21798 ext = { ExtensionType.client_hello_padding: PaddingExtension().create(padding_len) } node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["Large ClientHello padding"] = conversation # change ClientHello length to incorrect large length conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] # lowest size substitution, that causes OpenSSL 1.1.0 and 1.1.0a # to crash (SIGABRT) node = node.add_child( fuzz_message(ClientHelloGenerator(ciphers), substitutions={ 2: 0x55, 3: 0x55 })) node = node.add_child(ExpectClose()) conversations["Large incorrect ClientHello length"] = conversation # run the conversation good = 0 bad = 0 failed = [] sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], filter(lambda x: x[0] != 'sanity', conversations.items()), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): # # Test interleaving of Application Data with handshake messages, # requires server to support client initiated renegotiation # conversation = Connect("localhost", 4433) node = conversation #ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, # CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ClientHelloGenerator([CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA], session_id=bytearray(0), extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ApplicationDataGenerator(bytearray(b"hello server!\n"))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(b"hello server!\n"))) #node = node.add_child(ExpectApplicationData(bytearray(b"hello client!\n"))) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.next_sibling.next_sibling = ExpectApplicationData() # run the conversation good = 0 bad = 0 runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation for enc in ('handshake', 'application'): for padsize in [0, 2, 5, 30]: conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) if enc == "application": node = node.add_child(FinishedGenerator()) if padsize: node = node.add_child(SetPaddingCallback( SetPaddingCallback.fixed_length_cb(padsize))) node = node.add_child(RawMessageGenerator(ContentType.alert, bytearray(0))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message) node.next_sibling.add_child(ExpectClose()) if padsize: conversations["empty alert with {0} bytes of padding using {1} keys" .format(padsize, enc)] = conversation else: conversations["empty alert with no padding using {0} keys" .format(enc)] = conversation # run the conversation good = 0 bad = 0 failed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except Exception: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Check the tolerance of empty non-application-data messages. These should be") print("rejected with unexpected message alert (see Record Padding section of TLS1.3)") print("version: {0}\n".format(version)) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): """check if incorrect padding is rejected by server""" host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None dhe = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:d", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-d': dhe = True elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation if dhe: ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(RSA_SIG_ALL) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ext = None ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) fork = node node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) # handle servers which ask for client certificates fork.next_sibling = ExpectServerHelloDone() join = ClientKeyExchangeGenerator() fork.next_sibling.add_child(join) node = node.add_child(join) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation for pos, val in [ (-1, 0x01), (-1, 0xff), (-2, 0x01), (-2, 0xff), (-6, 0x01), (-6, 0xff), (-12, 0x01), (-12, 0xff), (-20, 0x01), (-20, 0xff), # we're generating at least 20 bytes of padding ]: conversation = Connect(host, port) node = conversation if dhe: ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(RSA_SIG_ALL) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ext = None ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) fork = node node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) # handle servers which ask for client certificates fork.next_sibling = ExpectServerHelloDone() join = ClientKeyExchangeGenerator() fork.next_sibling.add_child(join) node = node.add_child(join) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( fuzz_padding(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n"), xors={pos: val}, min_length=20)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) # node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["XOR position " + str(pos) + " with " + str(hex(val))] = \ conversation # zero-fill the padding conversation = Connect(host, port) node = conversation if dhe: ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(RSA_SIG_ALL) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ext = None ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) fork = node node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) # handle servers which ask for client certificates fork.next_sibling = ExpectServerHelloDone() join = ClientKeyExchangeGenerator() fork.next_sibling.add_child(join) node = node.add_child(join) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # block size for AES-128 is 16 bytes # SHA-1 MAC is 20 bytes long # length of "GET / HTTP" is 10 bytes # which means the padding will be two bytes - 1 byte of padding and one # byte length node = node.add_child( fuzz_padding(ApplicationDataGenerator(b"GET / HTTP"), substitutions={0: 0})) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["zero-filled"] = \ conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Check if incorrect padding is rejected by server") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): # # Test interleaving of Application Data with handshake messages, # requires server to support client initiated renegotiation # conversation = Connect("localhost", 4433) node = conversation #ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, # CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child( ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info: None})) node = node.add_child( ExpectServerHello(extensions={ExtensionType.renegotiation_info: None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child( ClientHelloGenerator( [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA], extensions={ExtensionType.renegotiation_info: None})) node = node.add_child( ExpectServerHello(extensions={ExtensionType.renegotiation_info: None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child( ApplicationDataGenerator(bytearray(b"hello server!\n"))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"hello server!\n"))) #node = node.add_child(ExpectApplicationData(bytearray(b"hello client!\n"))) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.next_sibling.next_sibling = ExpectApplicationData() # run the conversation good = 0 bad = 0 runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 else: bad += 1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """Check what signature algorithms server advertises""" hostname = "localhost" port = 4433 run_exclude = set() sigalgs = [SignatureScheme.rsa_pss_sha512, SignatureScheme.rsa_pss_sha384, SignatureScheme.rsa_pss_sha256, (HashAlgorithm.sha512, SignatureAlgorithm.rsa), (HashAlgorithm.sha384, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa), (HashAlgorithm.sha1, SignatureAlgorithm.rsa)] cert = None private_key = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:s:k:c:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '--help': help_msg() sys.exit(0) elif opt == '-s': sigalgs = sig_algs_to_ids(arg) elif opt == '-k': text_key = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_key = str(text_key, 'utf-8') private_key = parsePEMKey(text_key, private=True) elif opt == '-c': text_cert = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_cert = str(text_cert, 'utf-8') cert = X509() cert.parse(text_cert) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} # sanity check for Client Certificates conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {ExtensionType.signature_algorithms : SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1', 'md5']])} node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["sanity"] = conversation if cert and private_key: # sanity check for Client Certificates conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {ExtensionType.signature_algorithms : SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1', 'md5']])} node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(CertificateVerifyGenerator(private_key)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["with certificate"] = conversation # verify the advertised hashse conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {ExtensionType.signature_algorithms : SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1', 'md5']])} node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest(sigalgs)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["check sigalgs in cert request"] = conversation # run the conversation good = 0 bad = 0 failed = [] # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], filter(lambda x: x[0] != 'sanity', conversations.items()), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test to verify if server accepts empty certificate messages and") print("advertises only expected signature algotithms in Certificate") print("Request message\n") print("Test version 1\n") print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 fatal_alert = "decode_error" run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:", ["help", "alert="]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '--alert': fatal_alert = arg elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3))) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) # implicit SHA-1 check from TLS RFC (if no sig_algs => SHA-1 is implied) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create([(HashAlgorithm.sha1, SignatureAlgorithm.rsa)]) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) # implicit SHA-1 check from Client Hello ext node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["explicit SHA-1+RSA"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create([(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) # implicit SHA-256 check from Client Hello ext node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["explicit SHA-256+RSA"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create([(0, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa)]) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance none+RSA"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create([(10, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa)]) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance 10+RSA method"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create(list(chain( ((i, SignatureAlgorithm.rsa) for i in range(10, 224)), [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]))) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance 215 RSA methods"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create(list(chain( ((i, j) for i in range(10, 224) for j in range(10, 21)), [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]))) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) # OpenSSL sends the list of advertised and it doesn't fit a single # application data node = node.add_child(Close()) conversations["tolerance 2355 methods"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create(list(chain( ((i, j) for i in range(10, 224) for j in range(21, 59)), [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]))) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance 8132 methods"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create(list(chain( ((i, j) for i in range(10, 224) for j in range(10, 121)), [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]))) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance 23754 methods"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() # generate maximum number of methods (4 bytes for extensions header, # 2 bytes for length of list inside extension, leaving 65528 bytes) sig_alg.create(list(chain( ((i, j) for i in range(10, 224) for j in range(10, 163)), ((i, 163) for i in range(10, 31)), [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]))) ext = {ExtensionType.signature_algorithms: sig_alg} node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance max (32764) number of methods"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create([]) ext = {ExtensionType.signature_algorithms: sig_alg} hello = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(hello) node = node.add_child(ExpectAlert(AlertLevel.fatal, getattr(AlertDescription, fatal_alert))) node = node.add_child(ExpectClose()) conversations["empty list of signature methods"] = \ conversation for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] sig_alg = SignatureAlgorithmsExtension() sig_alg.create([(HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha1, SignatureAlgorithm.rsa)]) ext = {ExtensionType.signature_algorithms: sig_alg} hello = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(fuzz_message(hello, xors={-5:i})) node = node.add_child(ExpectAlert(AlertLevel.fatal, getattr(AlertDescription, fatal_alert))) node = node.add_child(ExpectClose()) conversations["fuzz length inside extension to {0}".format(4^i)] = \ conversation # run the conversation good = 0 bad = 0 failed = [] # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], filter(lambda x: x[0] != 'sanity', conversations.items()), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 print("OK") else: bad+=1 failed.append(c_name) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): """ Check SSLv2Hello support Test if the server supports SSLv2-style Client Hello messages for negotiating TLS connections """ conversations = {} host = "localhost" port = 4433 argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, ssl2=True)) ext={ExtensionType.renegotiation_info:None} node = node.add_child(ExpectServerHello(extensions=ext)) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.child = ExpectClose() # if we're doing TLSv1.0 the server should be doing 1/n-1 splitting node.next_sibling = ExpectApplicationData() node = node.next_sibling node.next_sibling = ExpectClose() conversations["SSLv2 Client Hello"] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None fatal_alert = "decode_error" run_exclude = set() expected_failures = {} last_exp_tmp = None no_sha1 = False expected_signature = SignatureAlgorithm.rsa expected_sig_list = RSA_SIG_ALL argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:x:X:", ["help", "alert=", "no-sha1", "ecdsa"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '--alert': fatal_alert = arg elif opt == '--no-sha1': no_sha1 = True elif opt == '--ecdsa': expected_signature = SignatureAlgorithm.ecdsa expected_sig_list = ECDSA_SIG_ALL elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(SIG_ALL) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ext = {} ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) if no_sha1: node = node.add_child(ExpectServerHello(version=(3, 3))) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure) node.next_sibling.add_child(ExpectClose()) alt = node.next_sibling node = node.add_child(ExpectCertificate()) node.add_child(alt) else: node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) # implicit SHA-1 check from Client Hello ext node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["implicit SHA-1 check"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = [(HashAlgorithm.sha1, expected_signature)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) if no_sha1: node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectClose()) else: node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) # implicit SHA-1 check from Client Hello ext node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["explicit SHA-1+RSA/ECDSA"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = [(HashAlgorithm.sha256, expected_signature)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) # implicit SHA-256 check from Client Hello ext node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["explicit SHA-256+RSA or ECDSA"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = [(0, expected_signature), (HashAlgorithm.sha256, expected_signature)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance none+RSA or ECDSA"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = [(10, expected_signature), (HashAlgorithm.sha256, expected_signature)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance 10+RSA or ECDSA method"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = list( chain(((i, expected_signature) for i in range(10, 224)), [(HashAlgorithm.sha256, expected_signature)])) ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance 215 RSA or ECDSA methods"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = list( chain(((i, j) for i in range(10, 224) for j in range(10, 21)), [(HashAlgorithm.sha256, expected_signature)])) ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) # OpenSSL sends the list of advertised and it doesn't fit a single # application data node = node.add_child(Close()) conversations["tolerance 2355 RSA or ECDSA methods"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = list( chain(((i, j) for i in range(10, 224) for j in range(21, 59)), [(HashAlgorithm.sha256, expected_signature)])) ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance 8132 RSA or ECDSA methods"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sig_alg = SignatureAlgorithmsExtension() sig_alg.create( list( chain(((i, j) for i in range(10, 224) for j in range(10, 121)), [(HashAlgorithm.sha256, expected_signature)]))) ext = {ExtensionType.signature_algorithms: sig_alg} ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance 23754 RSA or ECDSA methods"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sig_alg = SignatureAlgorithmsExtension() # generate maximum number of methods (4 bytes for extensions header, # 2 bytes for length of list inside extension, leaving 65528 bytes) sig_alg.create( list( chain(((i, j) for i in range(10, 224) for j in range(10, 163)), ((i, 163) for i in range(10, 27)), [(HashAlgorithm.sha256, expected_signature)]))) ext = {ExtensionType.signature_algorithms: sig_alg} ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance max (32760) number of methods"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] # generate maximum number of methods for 2 extensions # (4 bytes for extensions header, 2 bytes for length of list inside # extension leaving 65522 bytes) sigs = list( chain(((i, j) for i in range(10, 224) for j in range(10, 86)), ((i, 163) for i in range(10, 123)), [(HashAlgorithm.sha256, expected_signature)])) ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(sigs) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance 32758 methods with sig_alg_cert"] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] # generate maximum number of methods for 2 extensions # (4 bytes for extensions header, 2 bytes for length of list inside # extension leaving 65522 bytes) n = 32757 n = n - 1 # this is the mandatory method in the end n = n - len( expected_sig_list) # number of methods in sig_alg_cert extension sigs = list( chain(((i, j) for i in range(10, 224) for j in range(10, (n // 214) + 10)), ((i, 163) for i in range(10, (n % 214) + 10)), [(HashAlgorithm.sha256, expected_signature)])) ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) valid = [(HashAlgorithm.sha256, expected_signature)] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=valid)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( Close()) # OpenSSL lists them, which makes the response huge conversations["tolerance max {0} number of methods with sig_alg_cert". format(n)] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sigs = [] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(SIG_ALL) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) hello = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(hello) node = node.add_child( ExpectAlert(AlertLevel.fatal, getattr(AlertDescription, fatal_alert))) node = node.add_child(ExpectClose()) conversations["empty list of signature methods"] = \ conversation # generate maximum number of methods for 2 extensions # (4 bytes for extensions header, 2 bytes for length of list inside # extension leaving 65522 bytes) for n in [215, 2355, 8132, 23754, 32757]: conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] n = n - 1 # this is the mandatory method in the end n = n - len( expected_sig_list) # number of methods in sig_alg_cert extension sigs = [(HashAlgorithm.sha1, SignatureAlgorithm.dsa)] * n sigs += [(HashAlgorithm.sha256, expected_signature)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) # ApplicationData message may show up 1 to many times node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) cycle_alert = ExpectAlert() node = node.add_child(cycle_alert) node.next_sibling = ExpectApplicationData() node.next_sibling.add_child(cycle_alert) node.next_sibling.next_sibling = ExpectClose() conversations["duplicated {0} non-rsa schemes".format( n)] = conversation conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] # Add all supported sig_algs, put rsa(or ecdsa if --ecdsa used) at the end first = 'ecdsa' last = 'rsa' if expected_signature == SignatureAlgorithm.ecdsa: first = 'rsa' last = 'ecdsa' sig_algs = [] for sig_alg in [first, 'dsa']: sig_algs += [(getattr(HashAlgorithm, x), getattr(SignatureAlgorithm, sig_alg))\ for x in ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']] sig_algs += [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_rsae_sha384, SignatureScheme.rsa_pss_rsae_sha512, SignatureScheme.rsa_pss_pss_sha256, SignatureScheme.rsa_pss_pss_sha384, SignatureScheme.rsa_pss_pss_sha512 ] # ed25519(0x0807), ed448(0x0808) sig_algs += [(8, 7), (8, 8)] sig_algs += [(getattr(HashAlgorithm, x), getattr(SignatureAlgorithm, last))\ for x in ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sig_algs), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(expected_sig_list) } ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) # ApplicationData message may show up 1 to many times node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) cycle_alert = ExpectAlert() node = node.add_child(cycle_alert) node.next_sibling = ExpectApplicationData() node.next_sibling.add_child(cycle_alert) node.next_sibling.next_sibling = ExpectClose() conversations["unique and well-known sig_algs, {0} algorithm last".format( last)] = conversation for i in range(1, 0x100): conversation = Connect(host, port) node = conversation groups = [GroupName.secp256r1] ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] sig_alg = SignatureAlgorithmsExtension() sig_alg.create([(HashAlgorithm.sha256, expected_signature), (HashAlgorithm.sha1, expected_signature)]) ext = OrderedDict() ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = sig_alg hello = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(fuzz_message(hello, xors={-5: i})) node = node.add_child( ExpectAlert(AlertLevel.fatal, getattr(AlertDescription, fatal_alert))) node = node.add_child(ExpectClose()) conversations["fuzz length inside extension to {0}".format(4^i)] = \ conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK") else: bad += 1 failed.append(c_name) print("Signature Algorithms in TLS 1.2") print("Check if valid signature algorithm extensions are accepted and") print("invalid properly rejected by the TLS 1.2 server.\n") print("") print( "NOTE: For 'unique and well-known sig_algs..' conversation, the server" ) print( "must be configured to support only rsa_pkcs1_sha512 in case of an RSA" ) print("certificate and ecdsa+sha512 in case of an ECDSA certificate.") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad or xpass: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None srv_max_prot = None dhe = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:d", ["help", "server-max-protocol="]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-d': dhe = True elif opt == '--help': help_msg() sys.exit(0) elif opt == '--server-max-protocol': srv_max_prot = protocol_name_to_tuple(arg) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} # normal connection conversation = Connect(host, port) node = conversation if srv_max_prot == None or srv_max_prot == (3, 4): ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = \ ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() else: if dhe: ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(RSA_SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ext = None ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # TLS 1.3 downgrade check for prot in [(3, 1), (3, 2), (3, 3)]: if srv_max_prot is not None and prot > srv_max_prot: continue conversation = Connect(host, port) node = conversation if dhe: ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(RSA_SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ext = None ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child( ClientHelloGenerator(ciphers, extensions=ext, version=prot)) node = node.add_child( ExpectServerHello(server_max_protocol=srv_max_prot)) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) if prot < (3, 2): # 1/n-1 record splitting node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["TLS 1.3 downgrade check for Protocol {0}".format( prot)] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Check if server correctly return ServerHello Random ") print("with downgrade protection values to TLS1.2 and below ") print("clients\n") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None repeats = 32 argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:", ["help", "repeat="]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) elif opt == '--repeat': repeats = int(arg) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None collected_randoms = [] collected_key_shares = [] variables_check = \ {'ServerHello.random': collected_randoms, 'ServerHello.extensions.key_share.key_exchange': collected_key_shares} conversations = {} conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(CopyVariables(variables_check)) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation for group in [ GroupName.secp384r1, GroupName.secp521r1, GroupName.x25519, GroupName.x448, GroupName.ffdhe2048, GroupName.ffdhe3072 ]: conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [group] key_shares = [] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(CopyVariables(variables_check)) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["TLS 1.3 with {0}".format(GroupName.toStr(group))] \ = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue for i in range(repeats): print("\"{1}\" repeat {0}...".format(i, c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) failed_tests = uniqueness_check(variables_check, good + bad) if failed_tests: print("\n".join(failed_tests)) else: print("\n".join("{0} values: OK".format(i) for i in variables_check)) print('') print("Check if the ServerHello random values are unique") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad or xpass or failed_tests: sys.exit(1)
def main(): """check if atypical padding is accepted by server""" host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None dhe = False echo = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:d", ["help", "echo-headers"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-d': dhe = True elif opt == '--help': help_msg() sys.exit(0) elif opt == '--echo-headers': echo = True else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ext = None ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # check if SHA256 ciphers work conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ext = None ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity - SHA256 HMAC"] = conversation # check if SHA384 ciphers work conversation = Connect(host, port) node = conversation ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity - SHA384 HMAC"] = conversation # check if Encrypt Then Mac works conversation = Connect(host, port) node = conversation ext = {ExtensionType.encrypt_then_mac: AutoEmptyExtension()} if dhe: add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) extensions = {ExtensionType.encrypt_then_mac:None, ExtensionType.renegotiation_info:None} node = node.add_child(ExpectServerHello(extensions=extensions)) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity - encrypt then MAC"] = conversation # maximum size of padding conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ext = None ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\r\nX-bad: a\r\n\r\n" hmac_tag_length = 20 block_size = 16 # make sure that padding has full blocks to work with assert (len(text) + hmac_tag_length) % block_size == 0 node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=255)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["256 bytes of padding"] = \ conversation # maximum size of padding with SHA256 conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ext = None ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\r\nX-bad: aaaaa\r\n\r\n" hmac_tag_length = 32 block_size = 16 # make sure that padding has full blocks to work with assert (len(text) + hmac_tag_length) % block_size == 0, len(text) node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=255)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["256 bytes of padding with SHA256"] = \ conversation # ... and SHA384 conversation = Connect(host, port) node = conversation ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(RSA_SIG_ALL) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\r\nX-bad: aaaaa\r\n\r\n" hmac_tag_length = 48 block_size = 16 # make sure that padding has full blocks to work with assert (len(text) + hmac_tag_length) % block_size == 0, len(text) node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=255)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["256 bytes of padding with SHA384"] = \ conversation # longest possible padding with max size Application data conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ext = None ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\r\nX-bad: a\r\n" for i in range(3): text += b"X-ba" + compatAscii2Bytes(str(i)) + b": " + \ b"a" * (4096 - 9) + b"\r\n" text += b"X-ba3: " + b"a" * (4096 - 37) + b"\r\n" text += b"\r\n" assert len(text) == 2**14, len(text) node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=252)) if echo: node = node.add_child(ExpectApplicationData(size=2**14)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["2^14 bytes of AppData with 253 bytes of padding (SHA1)"] = \ conversation # longest possible padding with max size Application data (and EtM) conversation = Connect(host, port) node = conversation ext = {ExtensionType.encrypt_then_mac: AutoEmptyExtension()} if dhe: add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) extensions = {ExtensionType.encrypt_then_mac:None, ExtensionType.renegotiation_info:None} node = node.add_child(ExpectServerHello(extensions=extensions)) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\r\nX-bad: a\r\n" for i in range(3): text += b"X-ba" + compatAscii2Bytes(str(i)) + b": " + \ b"a" * (4096 - 9) + b"\r\n" text += b"X-ba3: " + b"a" * (4096 - 37) + b"\r\n" text += b"\r\n" assert len(text) == 2**14, len(text) node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=255)) if echo: node = node.add_child(ExpectApplicationData(size=2**14)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["2^14 bytes of AppData with 256 bytes of padding (SHA1 " "+ Encrypt then MAC)"] = \ conversation # longest possible padding with max size Application data with SHA256 conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] else: ext = None ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\r\nX-bad: a\r\n" for i in range(3): text += b"X-ba" + compatAscii2Bytes(str(i)) + b": " + \ b"a" * (4096 - 9) + b"\r\n" text += b"X-ba3: " + b"a" * (4096 - 37) + b"\r\n" text += b"\r\n" assert len(text) == 2**14, len(text) node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=255)) if echo: node = node.add_child(ExpectApplicationData(size=2**14)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["2^14 bytes of AppData with 256 bytes of padding (SHA256)"] = \ conversation conversation = Connect(host, port) node = conversation ext = {} add_dhe_extensions(ext) ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\r\nX-bad: a\r\n" for i in range(3): text += b"X-ba" + compatAscii2Bytes(str(i)) + b": " + \ b"a" * (4096 - 9) + b"\r\n" text += b"X-ba3: " + b"a" * (4096 - 37) + b"\r\n" text += b"\r\n" assert len(text) == 2**14, len(text) node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=255)) if echo: node = node.add_child(ExpectApplicationData(size=2**14)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["2^14 bytes of AppData with 256 bytes of padding (SHA384)"] = \ conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n" .format(expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test if server can handle records with large (but valid) padding") print("Tests both with small records and records that carry maximum amount") print("of user data.\n") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2*len(sanity_tests))) print("SKIP: {0}".format(len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed ,key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): """check if incorrect MAC hash is rejected by server""" host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\r\n\r\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) # sending of the close_notify reply to a close_notify is very unrealiable # ignore it not being sent node.next_sibling = ExpectClose() conversations["sanity"] = conversation for pos, val in [ (-1, 0x01), (-1, 0xff), (-2, 0x01), (-2, 0xff), (-6, 0x01), (-6, 0xff), (-12, 0x01), (-12, 0xff), (-20, 0x01), (-20, 0xff), # SHA-1 HMAC has just 20 bytes ]: conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(fuzz_mac(ApplicationDataGenerator( b"GET / HTTP/1.0\n\n"), xors={pos:val})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["XOR position " + str(pos) + " with " + str(hex(val))] = \ conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) app_data = b"GET / HTTP/1.0\r\nX-Fo: 0\r\n\r\n" assert (len(app_data) + 20 + 1) % 16 == 0 node = node.add_child(fuzz_mac(ApplicationDataGenerator(app_data), xors={pos:val})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["XOR position {0} with {1} (short pad)" .format(pos, hex(val))] = \ conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\nX-bad: aaaa\n\n" hmac_tag_length = 20 block_size = 16 # make sure that padding has full blocks to work with assert (len(text) + hmac_tag_length) % block_size == 0 node = node.add_child(fuzz_mac(fuzz_padding(ApplicationDataGenerator(text), min_length=255), xors={pos:val})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["XOR position {0} with {1} (long pad)" .format(pos, hex(val))] = \ conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n" .format(expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2*len(sanity_tests))) print("SKIP: {0}".format(len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed ,key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad or xpass: sys.exit(1)
def main(): # # Test if client hello with no valid cipher gets rejected # conversations = {} for name, ciphers in [ ("NULL_NULL cipher", [0x00]), ("FORTEZZA", range(0x1c,0x1e)), ("Unknown 0x0047", range(0x47, 0x60)), ("EXPORT1024", range(0x60, 0x66)), ("TLS_DHE_DSS_WITH_RC4_128_SHA", [0x66]), ("Unknown 0x006e", range(0x6e, 0x80)), ("GOST", range(0x80, 0x84)), ("Unknown 0x00c6", range(0xc6, 0xff)), ("TLS_EMPTY_RENEGOTIATION_INFO_SCSV", [0xff]), ("Unknown 0x0100", range(0x0100, 0x1001)), ("Unknown 0x2000", range(0x2000, 0x3001)), ("Unknown 0x3000", range(0x3000, 0x4001)), ("Unknown 0x4000", range(0x4000, 0x5001)), ("Unknown 0x5000", range(0x5000, 0x6001)), ("Unknown 0x6000", range(0x6000, 0x7001)), ("Unknown 0x7000", range(0x7000, 0x8001)), ("Unknown 0x8000", range(0x8000, 0x9001)), ("Unknwon 0x9000", range(0x9000, 0xa001)), ("Unknown 0xa000", range(0xa000, 0xb001)), ("Unknown 0xb000", range(0xb000, 0xc001)), ("Unknown 0xc0b0", range(0xc0b0, 0xd001)), ("Unknown 0xd000", range(0xd000, 0xe001)), ("Unknown 0xe000", range(0xe000, 0xf001)), ("Unknown 0xf000", range(0xf000, 0xffff)), ]: conversation = Connect("localhost", 4433) node = conversation node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations[name] = conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] print(str(conversation_name) + "...\n") runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation unassigned_ciphers = list(range(0x1306, 0x1400)) for un_cipher in unassigned_ciphers: conversation = Connect(host, port) node = conversation ciphers = [un_cipher, CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(cipher=CipherSuite.TLS_AES_128_GCM_SHA256)) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["non-existing cipher {0} with valid one".format(hex(un_cipher))] = conversation invalid_ciphers = unassigned_ciphers # unassigned ciphers invalid_ciphers += CipherSuite.tls12Suites # TLS 1.2 ciphers invalid_ciphers += CipherSuite.ssl3Suites for invalid_cipher in invalid_ciphers: conversation = Connect(host, port) node = conversation ciphers = [invalid_cipher] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node.add_child(ExpectClose()) conversations["only invalid cipher {0}".format(hex(invalid_cipher))] = conversation # run the conversation good = 0 bad = 0 failed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except Exception: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test with unassigned and invalid ciphers for TLS 1.3 protocol.") print("Check that communication with invalid ciphers is rejected") print("and that valid cipher is selected from advertised list") print("by TLS 1.3 server.") print("version: {0}\n".format(version)) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): conversations = {} conversation = Connect("localhost", 4433) node = conversation # any CBC will do, but the rest of code expects a 128 block cipher ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity check"] = conversation # CVE-2016-2107 reproducer # to reproduce the vulnerability we need to send a packet that decrypts # to 32 ASCII "A" bytes conversation = Connect("localhost", 4433) node = conversation # any CBC will do, but the rest of code expects a 128 bit block cipher and # 160 bit HMAC ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # we are encrypting 4 blocks, with 3 blocks (48 bytes) being data, MAC and padding node = node.add_child( fuzz_plaintext(ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n")) , substitutions={i : 0x31 for i in range(-1, -49, -1)})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["CVE-2016-2107"] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """check if app data records with zero payload are accepted by server""" conversations = {} conversation = Connect("localhost", 4433) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(0))) text = b"GET / HTTP/1.0\nX-bad: aaaa\n\n" node = node.add_child(ApplicationDataGenerator(text)) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["zero-length app data"] = \ conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] print(conversation_name + "...") runner = Runner(conversation) res = True #because we don't want to abort the testing and we are reporting #the errors to the user, using a bare except is OK #pylint: disable=bare-except try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False #pylint: enable=bare-except if res: good += 1 print("OK") else: bad += 1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """check if obsolete signature algorithm is rejected by server""" conversations = {} hostname = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None private_key = None cert = None argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:e:x:X:k:c:", ["help"]) for opt, arg in opts: if opt == '-k': text_key = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_key = str(text_key, 'utf-8') private_key = parsePEMKey(text_key, private=True) elif opt == '-c': text_cert = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_cert = str(text_cert, 'utf-8') cert = X509() cert.parse(text_cert) elif opt == '-h': hostname = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: run_only = set(argv) else: run_only = None if not private_key: raise ValueError("Specify private key file using -k") if not cert: raise ValueError("Specify certificate file using -c") conversation = Connect(hostname, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1', 'md5'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(CertificateVerifyGenerator(private_key)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["sanity"] = conversation for prf in ['sha256', 'sha384']: for md in ['sha1', 'sha256', 'sha384', 'sha512']: conversation = Connect(hostname, port) node = conversation if prf == 'sha256': ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ciphers = [ CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1', 'md5'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child( CertificateVerifyGenerator(private_key, msg_alg=(getattr(HashAlgorithm, md), SignatureAlgorithm.rsa))) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator( AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["check {0} w/{1} PRF".format(md, prf)] = \ conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) print("Certificate Verify test version 5") sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None #because we don't want to abort the testing and we are reporting #the errors to the user, using a bare except is OK #pylint: disable=bare-except try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False #pylint: enable=bare-except if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None dhe = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:d", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-d': dhe = True elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation if dhe: ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(SIG_ALL) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ext = None ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Basic conversation script; check basic communication with typical") print("cipher, TLS 1.2 or earlier and RSA key exchange (or (EC)DHE if") print("-d option is used)\n") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # Send zero-length application data between normal application data conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET /"))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"HTTP/1."))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["zero-length app data"] = conversation # Send zero-length application data with padding conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(SetPaddingCallback( SetPaddingCallback.fixed_length_cb(30))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET /"))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"HTTP/1."))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["zero-length app data with padding"] = conversation # Send zero-length application data with large paddings conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(SetPaddingCallback( SetPaddingCallback.fill_padding_cb)) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET /"))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"HTTP/1."))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ApplicationDataGenerator( bytearray(b"0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["zero-length app data with large padding"] = conversation # Send zero-length application data while handshaking conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(0))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message) node.next_sibling.add_child(ExpectClose()) conversations["zero-length app data during handshake"] = conversation # Send zero-length application data while handshaking with padding conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(SetPaddingCallback( SetPaddingCallback.fixed_length_cb(30))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message) node.next_sibling.add_child(ExpectClose()) conversations["zero-length app data with padding during handshake"] =\ conversation # Send zero-length application data while handshaking with large padding conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(SetPaddingCallback( SetPaddingCallback.fill_padding_cb)) node = node.add_child(ApplicationDataGenerator(bytearray(0))) # The server may send NST before receiving client Finished # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message) node.next_sibling.add_child(ExpectClose()) conversations["zero-len app data with large padding during handshake"] =\ conversation # Send a zero-length application data interleaved in handshake fragment_list = [] conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) hello_gen = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(split_message(hello_gen, fragment_list, 2)) node = node.add_child(PopMessageFromList(fragment_list)) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node.add_child(ExpectClose()) conversations["zero-length app data interleaved in handshake"] =\ conversation # Send zero-len app data with padding interleaved in handshaking fragment_list = [] conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) hello_gen = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(split_message(hello_gen, fragment_list, 2)) node = node.add_child(PopMessageFromList(fragment_list)) node = node.add_child(SetPaddingCallback( SetPaddingCallback.fixed_length_cb(30))) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node.add_child(ExpectClose()) conversations["zero-len app data with padding interleaved in " "handshake"] = conversation # Send zero-len app data with large padding interleaved in handshaking fragment_list = [] conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) hello_gen = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(split_message(hello_gen, fragment_list, 2)) node = node.add_child(PopMessageFromList(fragment_list)) node = node.add_child(SetPaddingCallback( SetPaddingCallback.fill_padding_cb)) node = node.add_child(ApplicationDataGenerator(bytearray(0))) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node.add_child(ExpectClose()) conversations["zero-len app data with large padding interleaved in " "handshake"] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n" .format(expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("TLS 1.3 zero-length Application Data") print("Check if zero-length Application Data records handling is") print("correct\n.") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2*len(sanity_tests))) print("SKIP: {0}".format(len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed ,key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): """check if atypical padding is accepted by server""" host = "localhost" port = 4433 num_limit = None run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\nX-bad: aaaa\n\n" hmac_tag_length = 20 block_size = 16 # make sure that padding has full blocks to work with assert (len(text) + hmac_tag_length) % block_size == 0 node = node.add_child( fuzz_padding(ApplicationDataGenerator(text), min_length=255)) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["256 bytes of padding"] = \ conversation # run the conversation good = 0 bad = 0 failed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None coalescing = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:", ["help", "coalescing"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--coalescing': coalescing = True elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( KeyUpdateGenerator(message_type=KeyUpdateMessageType.update_requested)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectKeyUpdate( message_type=KeyUpdateMessageType.update_not_requested) node = node.next_sibling.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations[ "post-handshake KeyUpdate msg with update_request"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( KeyUpdateGenerator( message_type=KeyUpdateMessageType.update_not_requested)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations[ "post-handshake KeyUpdate msg with update_not_request"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( truncate_handshake( KeyUpdateGenerator( message_type=KeyUpdateMessageType.update_requested), 1)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error) node.next_sibling.add_child(ExpectClose()) conversations["empty KeyUpdate message"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( pad_handshake( KeyUpdateGenerator( message_type=KeyUpdateMessageType.update_requested), 1)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error) node.next_sibling.add_child(ExpectClose()) conversations["large KeyUpdate message"] = conversation for msg_type in range(2, 256): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(KeyUpdateGenerator(message_type=msg_type)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter) node.next_sibling.add_child(ExpectClose()) conversations["invalid message_type - {0}, in KeyUpdate msg".format( msg_type)] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator(bytearray(b"GET"))) node = node.add_child( KeyUpdateGenerator(message_type=KeyUpdateMessageType.update_requested)) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectKeyUpdate( message_type=KeyUpdateMessageType.update_not_requested) node = node.next_sibling.add_child( ApplicationDataGenerator(bytearray(b" / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations[ "app data split, conversation with KeyUpdate msg"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) number_of_ku_msg = 32 for i in range(number_of_ku_msg): node = node.add_child( KeyUpdateGenerator( message_type=KeyUpdateMessageType.update_requested)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectKeyUpdate( message_type=KeyUpdateMessageType.update_not_requested) node = node.next_sibling # the server can coalesce the respone to a single key update # or it may reply to every message in particular if not coalescing: for i in range(number_of_ku_msg - 1): node = node.add_child( ExpectKeyUpdate( message_type=KeyUpdateMessageType.update_not_requested)) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["multiple KeyUpdate messages"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) fragment_list = [] keyupdate_gen = KeyUpdateGenerator( message_type=KeyUpdateMessageType.update_requested) node = node.add_child(split_message(keyupdate_gen, fragment_list, 2)) node = node.add_child(FlushMessageList(fragment_list)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectKeyUpdate( message_type=KeyUpdateMessageType.update_not_requested) node = node.next_sibling.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["fragmented keyupdate msg"] = conversation for fragment_len in range(1, 5): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create( key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) fragment_list = [] keyupdate_gen = KeyUpdateGenerator( message_type=KeyUpdateMessageType.update_requested) node = node.add_child( split_message(keyupdate_gen, fragment_list, fragment_len)) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(FlushMessageList(fragment_list)) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message) node.next_sibling.add_child(ExpectClose()) conversations[ "{0}/{1} fragmented keyupdate msg, appdata between".format( fragment_len, 5 - fragment_len)] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test with KeyUpdate msg with different msg_type or fragmented msg.") print("Verify that server will correctly handle updating the keys") print("or refuse the connection with relevant Alert msg.") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): """Test if server supports all common hash algorithms in DHE_RSA kex""" conversations = {} for cipher in [CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256]: for hash_alg in ["sha1", "sha224", "sha256", "sha384", "sha512"]: conversation = Connect("localhost", 4433) node = conversation ciphers = [cipher] sig_algs = [(getattr(HashAlgorithm, hash_alg), SignatureAlgorithm.rsa)] ext = SignatureAlgorithmsExtension().create(sig_algs) node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType. renegotiation_info:None, ExtensionType. signature_algorithms: ext})) node = node.add_child(ExpectServerHello(version=(3, 3), extensions={ExtensionType. renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=sig_algs)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations[CipherSuite.ietfNames[cipher] + " " + hash_alg + " signature"] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """ Test if the server will not accept cipher forcing from client client forces 3DES """ conversations = {} host = "localhost" port = 4433 argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) for prot_vers, proto_name in { (0, 2): "SSLv2", (3, 0): "SSLv3", (3, 1): "TLSv1.0" }.items(): for cipher_id, cipher_name in { CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5: "DES-CBC3-MD5" }.items(): # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [ CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_IDEA_128_CBC_WITH_MD5, CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5 ] node = node.add_child( ClientHelloGenerator(ciphers, version=prot_vers, ssl2=True)) # we can get a ServerHello with no ciphers: node = node.add_child(ExpectServerHello2()) # or we can get an error stright away, and connection closure node.next_sibling = ExpectSSL2Alert(SSL2ErrorDescription.no_cipher) node.next_sibling.add_child(ExpectClose()) alternative = node.next_sibling # or the server may close the connection right away (likely in # case SSLv2 is completely disabled) alternative.next_sibling = ExpectClose() alternative = alternative.next_sibling # or finally, we can get a TLS Alert message alternative.next_sibling = ExpectAlert() alternative.next_sibling.add_child(ExpectClose()) # in case we got ServerHello, try to force one of the ciphers node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) # it should result in error node = node.add_child(ExpectSSL2Alert()) # or connection close node.next_sibling = ExpectClose() # in case of error, we expect the server to close connection node.add_child(ExpectClose()) conversations["Connect with {1} {0}".format( cipher_name, proto_name)] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good += 1 print("OK\n") else: bad += 1 print("Note: SSLv2 was officially deprecated (MUST NOT use) in 2011, see") print(" RFC 6176.") print( " If one or more of the tests fails because of error in form of") print("") print(" Unexpected message from peer: Handshake()") print("") print(" With any number inside parethensis, and the server is") print(" configured to not support SSLv2, it means it most") print(" likely is vulnerable to CVE-2015-3197.") print(" In case it's a RC4 or 3DES cipher, you may verify that it") print(" really supports it using:") print(" test-sslv2-connection.py") print("") print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): # # Test if client hello with garbage at the end gets rejected # conversations = {} # test if server doesn't interpret extensions past extensions length conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(pad_handshake(ClientHelloGenerator(ciphers, extensions={}), # empty renegotiation info pad=bytearray(b'\xff\x01\x00\x01\x00'))) # responding to a malformed client hello is not correct, but tested below node = node.add_child(ExpectServerHello(extensions={})) node.next_sibling = ExpectAlert() node.next_sibling.next_sibling = ExpectClose() conversations["extension past extensions"] = conversation for name, pad_len, pad_byte in [ ("small pad", 1, 0), ("small pad", 2, 0), ("small pad", 3, 0), ("small pad", 1, 0xff), ("small pad", 2, 0xff), ("small pad", 3, 0xff), ("medium pad", 256, 0), ("big pad", 4096, 0), ("huge pad", 2**16, 0), ("small truncate", -1, 0), ("small truncate", -2, 0), ("small truncate", -3, 0), ("small truncate", -4, 0), ("small truncate", -5, 0), ("small truncate", -6, 0), # 7 bytes truncates whole 'extensions' creating # a valid message #("small truncate", -7, 0), ("hello truncate", -8, 0), ("hello truncate", -9, 0), ("hello truncate", -10, 0), ("hello truncate", -11, 0), ("hello truncate", -12, 0), ("hello truncate", -13, 0), ]: conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(pad_handshake(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info: None}), pad_len, pad_byte)) # we expect Alert and Close or just Close node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(ExpectClose()) if "pad" in name: conversations[name + ": " + str(pad_len) + " of \"" + str(pad_byte) + "\" byte padding"] = conversation else: conversations[name + ": " + str(-pad_len) + " of bytes truncated"] = conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] print(str(conversation_name) + "...\n") runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None fatal_alert = "decode_error" run_exclude = set() expected_failures = {} last_exp_tmp = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:", ["help", "alert="]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--alert': fatal_alert = arg elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pkcs1_sha1, SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance legacy RSA PKCS#1.5"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [(10, SignatureAlgorithm.rsa), SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["tolerance unallocated 0x0A01 (10+RSA) method"] = conversation # 32717 is the maximum possible amount of methods that can fit into the # ClientHello packet -- in TLS 1.3, there are also other mandatory # extensions for n in [215, 2355, 8132, 23754, 32717]: conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) n = n - 2 # these are the mandatory methods in the end sig_algs = [(HashAlgorithm.sha1, SignatureAlgorithm.dsa)] * n sig_algs += [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) # ApplicationData message may show up 1 to many times node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) cycle_alert = ExpectAlert() node = node.add_child(cycle_alert) node.next_sibling = ExpectApplicationData() node.next_sibling.add_child(cycle_alert) node.next_sibling.next_sibling = ExpectClose() conversations["duplicated {0} non-rsa schemes".format(n)] = conversation for n in [215, 2355, 8132, 23754, 32717]: conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) n = n - 2 # these are the mandatory methods in the end sig_algs = [SignatureScheme.rsa_pkcs1_sha1] * n sig_algs += [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) # ApplicationData message may show up 1 to many times node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) cycle_alert = ExpectAlert() node = node.add_child(cycle_alert) node.next_sibling = ExpectApplicationData() node.next_sibling.add_child(cycle_alert) node.next_sibling.next_sibling = ExpectClose() conversations["{0} invalid schemes".format(n)] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) # Add all supported sig_algs, put rsa at the end sig_algs = [] for sig_alg in ['ecdsa', 'dsa','rsa']: sig_algs += [(getattr(HashAlgorithm, x), getattr(SignatureAlgorithm, sig_alg))\ for x in ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512']] # ed25519(0x0807), ed448(0x0808) sig_algs += [(8, 7), (8, 8)] sig_algs += [SignatureScheme.rsa_pss_pss_sha256, SignatureScheme.rsa_pss_pss_sha384, SignatureScheme.rsa_pss_pss_sha512, SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_rsae_sha384, SignatureScheme.rsa_pss_rsae_sha512] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["unique and well-known sig_algs, rsa algorithms last"] = conversation # 32717 is the maximum possible amount of methods that can fit into the # ClientHello packet -- in TLS 1.3, there are also other mandatory # extensions for n in [215, 2355, 8132, 23754, 32717]: conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) n = n - 2 # these are the mandatory methods in the end sig_algs = list(chain( ((i, j) for i in range(10, 224) for j in range(10, (n // 214) + 10)), ((i, 163) for i in range(10, (n % 214) + 10)), [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256])) ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() # OpenSSL sends the list of advertised and it doesn't fit a single # application data node = node.next_sibling.add_child(Close()) conversations["tolerance {0} methods".format(n)] = conversation # 32715 is the maximum possible amount of methods that can fit into the # ClientHello packet -- in TLS 1.3, there are also other mandatory # extensions n = 32715 conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) n = n - 2 # these are the mandatory methods in the end n = n - len(RSA_SIG_ALL) # number of methods in sig_alg_cert extension sig_algs = list(chain( ((i, j) for i in range(10, 224) for j in range(10, (n // 214) + 10)), ((i, 163) for i in range(10, (n % 214) + 10)), [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256])) ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() # OpenSSL sends the list of advertised and it doesn't fit a single # application data node = node.next_sibling.add_child(Close()) conversations["tolerance 32715 methods with sig_alg_cert"] = conversation # Use empty supported algorithm extension conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectAlert(AlertLevel.fatal, getattr(AlertDescription, fatal_alert))) node = node.add_child(ExpectClose()) conversations["empty list of signature methods"] = \ conversation # Only undefined algorithms conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sigs = [(HashAlgorithm.sha256, 24), # undefined signature algorithm (24, SignatureAlgorithm.rsa), # undefined hash algorithm (10, 10), # undefined pair (9, 24), # undefined pair (0xff, 0xff) # undefined pair ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sigs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.next_sibling = ExpectClose() conversations["only undefined sigalgs"] = conversation # RSA-PSS is mandatory # More thoroughly tested in scripts/test-tls13-pkcs-signature.py conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sigs = [SignatureScheme.rsa_pkcs1_sha1, SignatureScheme.rsa_pkcs1_sha512] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sigs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.next_sibling = ExpectClose() conversations["only legacy sigalgs"] = conversation # padded extension conversation = Connect(host, port) ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ TLSExtension(extType=ExtensionType.signature_algorithms) \ .create(bytearray(b'\x00\x04' # length of array b'\x08\x04' # rsa_pss_rsae_sha256 b'\x08\x09' # rsa_pss_pss_sha256 b'\x04\x03')) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["padded sigalgs"] = conversation # send properly formatted one byte extension conversation = Connect(host, port) ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ TLSExtension(extType=ExtensionType.signature_algorithms) \ .create(bytearray(b'\x00\x01' # length of array b'\x02')) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["one byte array"] = conversation # send properly formatted three byte extension conversation = Connect(host, port) ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ TLSExtension(extType=ExtensionType.signature_algorithms) \ .create(bytearray(b'\x00\x05' # length of array b'\x08\x04' # rsa_pss_rsae_sha256 b'\x08\x09' # rsa_pss_pss_sha256 b'\x02')) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["three byte array"] = conversation # Fuzz the length of supported extensions for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256] ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) hello = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(fuzz_message(hello, xors={-5:i})) node = node.add_child(ExpectAlert(AlertLevel.fatal, getattr(AlertDescription, fatal_alert))) node = node.add_child(ExpectClose()) conversations["fuzz length inside extension to {0}".format(4^i)] = \ conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n" .format(expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Signature Algorithms in TLS 1.3") print("Check if valid signature algorithm extensions are accepted and") print("invalid properly rejected by the TLS 1.3 server.\n") print("Server must be configured to support only rsa_pss_rsae_sha512") print("signature algorithm.") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2*len(sanity_tests))) print("SKIP: {0}".format(len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed ,key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): # # Test interleaving of Application Data with handshake messages, # requires an HTTP-like server with support for client initiated # renegotiation # conversations = {} conver = Connect("localhost", 4433) node = conver #ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, # CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) fragment_list = [] node = node.add_child(split_message(ClientHelloGenerator([CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA], extensions={ExtensionType.renegotiation_info:None}), fragment_list, 30)) # interleaved AppData node = node.add_child(ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0"))) node = node.add_child(FlushMessageList(fragment_list)) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(b"\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["Application data inside Client Hello"] = conver conver = Connect("localhost", 4433) node = conver #ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, # CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ClientHelloGenerator([CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA], extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) fragment_list = [] node = node.add_child(split_message(ClientKeyExchangeGenerator(), fragment_list, 30)) # interleaved AppData node = node.add_child(ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0"))) node = node.add_child(FlushMessageList(fragment_list)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(b"\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["Application data inside Client Key Exchange"] = conver # CCS is one byte, can't split it #conversations["Application data inside Change Cipher Spec"] = conver conver = Connect("localhost", 4433) node = conver #ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, # CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ClientHelloGenerator([CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA], extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) fragments = [] node = node.add_child(split_message(FinishedGenerator(), fragments, 10)) # interleaved AppData node = node.add_child(ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0"))) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["Application data inside Finished"] = conver # run the conversation good = 0 bad = 0 for conver_name in conversations: conversation = conversations[conver_name] runner = Runner(conversation) print(conver_name + "...") res = True try: runner.run() except: print("\n") print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None num_bytes = 2**14 cookie = False dhe = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:d", ["help", "num-bytes=", "cookie"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) elif opt == '--num-bytes': num_bytes = int(arg) elif opt == '--cookie': cookie = True elif opt == '-d': dhe = True else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} # sanity check conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # sanity check with PSK binders conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), 0) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid PSK"] = conversation # fake 0-RTT resumption with HRR and early data after second client hello conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [0x1300, GroupName.secp256r1] key_shares = [KeyShareEntry().create(0x1300, bytearray(b'\xab' * 32))] ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) ext = {} if cookie: ext[ExtensionType.cookie] = None ext[ExtensionType.key_share] = None ext[ExtensionType.supported_versions] = None node = node.add_child(ExpectHelloRetryRequest(extensions=ext)) node = node.add_child(ExpectChangeCipherSpec()) ext = OrderedDict() key_shares = [] for group in [GroupName.secp256r1]: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) if cookie: ext[ExtensionType.cookie] = ch_cookie_handler ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create( [iden], [getRandomBytes(32)]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child( PlaintextMessageGenerator(ContentType.application_data, getRandomBytes(64))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac) node.next_sibling.add_child(ExpectClose()) conversations["handshake with 0-RTT, HRR and early data after 2nd Client Hello"]\ = conversation # fake 0-RTT resumption with HRR conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [0x1300, GroupName.secp256r1] key_shares = [KeyShareEntry().create(0x1300, bytearray(b'\xab' * 32))] ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) ext = {} if cookie: ext[ExtensionType.cookie] = None ext[ExtensionType.key_share] = None ext[ExtensionType.supported_versions] = None node = node.add_child(ExpectHelloRetryRequest(extensions=ext)) node = node.add_child(ExpectChangeCipherSpec()) ext = OrderedDict() key_shares = [] for group in [GroupName.secp256r1]: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) if cookie: ext[ExtensionType.cookie] = ch_cookie_handler ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create( [iden], [getRandomBytes(32)]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT and HRR"] = conversation # fake 0-RTT resumption with fragmented early data conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT with fragmented early data"]\ = conversation # fake 0-RTT and early data spliced into the Finished message conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) finished_fragments = [] node = node.add_child( split_message(FinishedGenerator(), finished_fragments, 16)) # early data spliced into the Finished message node = node.add_child( PlaintextMessageGenerator(ContentType.application_data, getRandomBytes(64))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac) node.next_sibling.add_child(ExpectClose()) conversations["undecryptable record later in handshake together with early_data"]\ = conversation # fake 0-RTT resumption and CCS between fake early data conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child(ChangeCipherSpecGenerator(fake=True)) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT and CCS between early data records"]\ = conversation # fake 0-RTT resumption and CCS conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ChangeCipherSpecGenerator(fake=True)) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT and CCS"] = conversation # fake 0-RTT resumption with unknown version conversation = Connect(host, port) node = conversation ext = OrderedDict() groups = [GroupName.secp256r1, GroupName.ffdhe2048] if dhe: ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([(3, 5), (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) # section D.3 of draft 28 states that client that receives TLS 1.2 # ServerHello as a reply to 0-RTT Client Hello MUST fail a connection # consequently, the server does not need to be able to ignore early data # in TLS 1.2 mode node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node.add_child(ExpectClose()) conversations[ "handshake with invalid 0-RTT and unknown version (downgrade to TLS 1.2)"] = conversation # fake 0-RTT resumption conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT"] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Basic check if TLS 1.3 server can handle 0-RTT handshake") print("Verify that the server can handle a 0-RTT handshake from client") print("even if (or rather, especially if) it doesn't support 0-RTT.\n") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): """check if fuzzed ciphertext is rejected by server""" conversations = {} # 8 chars: explicit nonce # 16 chars: AES-CTR encrypt: GET / HTTP/1.0\n\n # 16 chars: GCM tag 128 bit # 1 char: experimentally determined there mysteriously is one more byte # in the message. fuzzes = [(-i, 1) for i in range(1,8+16+16+1)] for pos, val in fuzzes: conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(fuzz_encrypted_message( ApplicationDataGenerator(b"GET / HTTP/1.0\n\n"), xors={pos:val})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["XOR position " + str(pos) + " with " + str(hex(val))] = \ conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] print(conversation_name + "...") runner = Runner(conversation) res = True #because we don't want to abort the testing and we are reporting #the errors to the user, using a bare except is OK #pylint: disable=bare-except try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False #pylint: enable=bare-except if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): # # Test sending invalid (too short or too long) Finished messages # conversations = {} conver = Connect("localhost", 4433) node = conver #ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, # CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(pad_handshake(FinishedGenerator(), pad=bytearray(b'\xfa'))) #node = node.add_child(ExpectChangeCipherSpec()) #node = node.add_child(ExpectFinished()) #node = node.add_child(AlertGenerator(AlertLevel.warning, # AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["padded Finished"] = conver conver = Connect("localhost", 4433) node = conver #ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, # CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(truncate_handshake(FinishedGenerator(), 1)) #node = node.add_child(ExpectChangeCipherSpec()) #node = node.add_child(ExpectFinished()) #node = node.add_child(AlertGenerator(AlertLevel.warning, # AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["truncated Finished"] = conver # run the conversation good = 0 bad = 0 for conver_name in conversations: conversation = conversations[conver_name] runner = Runner(conversation) print(conver_name + "...") res = True try: runner.run() except: print("\n") print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """Test if client hello with no valid compression method gets rejected""" host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child( ClientHelloGenerator(ciphers, compression=range(1, 256))) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) node.add_child(ExpectClose()) conversations['invalid compression methods'] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, compression=[1])) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) node.add_child(ExpectClose()) conversations['only deflate compression method'] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Verify if server checks compressions field in ClientHello") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): """check if incorrect padding is rejected by server""" conversations = {} for pos, val in [ (-1, 0x01), (-1, 0xff), (-2, 0x01), (-2, 0xff), (-6, 0x01), (-6, 0xff), (-12, 0x01), (-12, 0xff), (-20, 0x01), (-20, 0xff), # we're generating at least 20 bytes of padding ]: conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(fuzz_padding(ApplicationDataGenerator( b"GET / HTTP/1.0\n\n"), xors={pos:val}, min_length=20)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) # node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["XOR position " + str(pos) + " with " + str(hex(val))] = \ conversation # zero-fill the padding conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # block size for AES-128 is 16 bytes # SHA-1 MAC is 20 bytes long # length of "GET / HTTP" is 10 bytes # which means the padding will be two bytes - 1 byte of padding and one # byte length node = node.add_child(fuzz_padding(ApplicationDataGenerator( b"GET / HTTP"), substitutions={0:0})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) # node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["zero-filled"] = \ conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] print(conversation_name + "...") runner = Runner(conversation) res = True #because we don't want to abort the testing and we are reporting #the errors to the user, using a bare except is OK #pylint: disable=bare-except try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False #pylint: enable=bare-except if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """Test if server provides unique DHE_RSA key shares.""" host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None repeats = 32 record_split = True argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:z", ["help", "repeat="]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-z': record_split = False elif opt == '--help': help_msg() sys.exit(0) elif opt == '--repeat': repeats = int(arg) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None collected_randoms = [] collected_key_shares = [] collected_session_ids = [] variables_check = \ {'ServerHello.random': collected_randoms, 'ServerKeyExchange.key_share': collected_key_shares, 'ServerHello.session_id': collected_session_ids} conversations = {} conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA] node = node.add_child( ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info: None})) node = node.add_child( ExpectServerHello(extensions={ExtensionType.renegotiation_info: None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(CopyVariables(variables_check)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation for prot in [(3, 0), (3, 1), (3, 2), (3, 3)]: for ssl2 in [True, False]: conversation = Connect(host, port, version=(0, 2) if ssl2 else (3, 0)) node = conversation ciphers = [ CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child( ClientHelloGenerator(ciphers, version=prot, ssl2=ssl2)) if prot > (3, 0): ext = {ExtensionType.renegotiation_info: None} else: ext = None node = node.add_child( ExpectServerHello(extensions=ext, version=prot)) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(CopyVariables(variables_check)) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) if prot < (3, 2) and record_split: # 1/n-1 record splitting node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["Protocol {0}{1}".format( prot, " in SSLv2 compatible ClientHello" if ssl2 else "")] = \ conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) regular_tests = [(k, v) for k, v in conversations.items() if k in run_only] else: regular_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue for i in range(repeats): print("\"{1}\" repeat {0}...".format(i, c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) failed_tests = uniqueness_check(variables_check, good + bad) if failed_tests: print("\n".join(failed_tests)) else: print("\n".join("{0} values: OK".format(i) for i in variables_check)) print('') print("Check if the server provided random values are unique") print("Checks random and session_id from Server Hello and DHE key share") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0 or failed_tests: sys.exit(1)
def main(): # # Test if server can handle handshake protocol messages fragmented over # multiple records # conversations = {} # 2**14-49 - max size of Client Hello for OpenSSL # 2**16-5 - max size of extensions in TLS # 2**14-52 - min size of extension that will cause the message to be # fragmented over multiple records # # note: None for record_len will cause the limit to be set to protocol # maximum - 2**14 for name, ext_len, record_len in [ ("small hello", 20, None), ("medium hello", 1024, None), ("big, non fragmented", 2**12, None), ("big, needs fragmentation", 2**14-49, None), ("big, needs fragmentation", 2**14-48, None), ("big, needs fragmentation", 2**15, None), ("maximum size", 2**16-5, None), ("small, reasonable fragmentation", 20, 1024), ("medium, reasonable fragmentation", 1024, 1024), ("big, reasonable fragmentation", 2**12, 1024), ("small, excessive fragmentation", 20, 20), ("medium, excessive fragmentation", 1024, 20), ("big, excessive fragmentation", 2**12, 20), ("small, maximum fragmentation", 20, 1), ("medium, maximum fragmentation", 1024, 1), ("maximum size without fragmentation", 2**14-53, None)]: padding_extension = lambda _,l=ext_len:TLSExtension().create(21, bytearray(l)) conversation = Connect("localhost", 4433) node = conversation node = node.add_child(SetMaxRecordSize(record_len)) ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions={21: padding_extension})) node = node.add_child(ExpectServerHello(extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) # RFCs do not consider Alerts special with regards to fragmentation #node = node.add_child(SetMaxRecordSize(2)) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() if record_len is None: record_len = "max" conversations[name + ": " + str(record_len) + " fragment - " + str(ext_len) + "B extension"] = conversation # check if records bigger than TLSPlaintext limit are rejected padding_extension = lambda _:TLSExtension().create(21, bytearray(2**14-52)) conversation = Connect("localhost", 4433) node = conversation node = node.add_child(SetMaxRecordSize(2**16-1)) ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers, extensions={21: padding_extension})) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["non fragmented, over fragmentation limit: " + str(2**16-1) + " fragment - " + str(2**14-52) + "B extension"] = conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] runner = Runner(conversation) print(str(conversation_name) + "...\n") res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good+=1 else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # run the conversation good = 0 bad = 0 failed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], islice( filter(lambda x: x[0] != 'sanity', conversations.items()), num_limit), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except Exception: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Basic communication test with TLS 1.3 server") print("Check if communication with typical group and cipher works with") print("the TLS 1.3 server.\n") print("version: {0}\n".format(version)) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): """Check that server propoerly rejects pkcs1 signatures in TLS 1.3""" hostname = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None cert = None private_key = None # algorithms to expect from server in Certificate Request cr_sigalgs = [SignatureScheme.ecdsa_secp521r1_sha512, SignatureScheme.ecdsa_secp384r1_sha384, SignatureScheme.ecdsa_secp256r1_sha256, (HashAlgorithm.sha224, SignatureAlgorithm.ecdsa), (HashAlgorithm.sha1, SignatureAlgorithm.ecdsa), SignatureScheme.rsa_pss_rsae_sha512, SignatureScheme.rsa_pss_pss_sha512, SignatureScheme.rsa_pss_rsae_sha384, SignatureScheme.rsa_pss_pss_sha384, SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256, SignatureScheme.rsa_pkcs1_sha512, SignatureScheme.rsa_pkcs1_sha384, SignatureScheme.rsa_pkcs1_sha256, SignatureScheme.rsa_pkcs1_sha224, SignatureScheme.rsa_pkcs1_sha1] # algorithms to advertise in ClientHello sig_algs = [SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256, SignatureScheme.rsa_pss_rsae_sha384, SignatureScheme.rsa_pss_pss_sha384] hashalgs = hashes_to_list("sha256 sha384 sha512") argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:s:k:c:", ["help", "hash-order="]) for opt, arg in opts: if opt == '-h': hostname = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) elif opt == '-s': cr_sigalgs = sig_algs_to_ids(arg) elif opt == '--hash-order': hashalgs = hashes_to_list(arg) elif opt == '-k': text_key = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_key = str(text_key, 'utf-8') private_key = parsePEMKey(text_key, private=True) elif opt == '-c': text_cert = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_cert = str(text_cert, 'utf-8') cert = X509() cert.parse(text_cert) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None if not cert or not private_key: raise Exception("A Client certificate and a private key are required") certType = cert.certAlg conversations = {} conversations_long = {} # sanity check for Client Certificates conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(CertificateVerifyGenerator(private_key)) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # verify the advertised hashes conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest(cr_sigalgs)) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["check sigalgs in cert request"] = conversation for sigalg in RSA_SIG_ALL: # set if test should succeed or fail based on cert type, # advertisement and forbidden algorithms expectPass = True if certType == "rsa" and sigalg in ( SignatureScheme.rsa_pss_pss_sha256, SignatureScheme.rsa_pss_pss_sha384, SignatureScheme.rsa_pss_pss_sha512): expectPass = False elif certType == "rsa-pss" and sigalg in ( SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_rsae_sha384, SignatureScheme.rsa_pss_rsae_sha512): expectPass = False # also verify that pkcs1 signatures are unconditionally refused if sigalg in ((HashAlgorithm.md5, SignatureAlgorithm.rsa), SignatureScheme.rsa_pkcs1_sha1, SignatureScheme.rsa_pkcs1_sha224, SignatureScheme.rsa_pkcs1_sha256, SignatureScheme.rsa_pkcs1_sha384, SignatureScheme.rsa_pkcs1_sha512): expectPass = False # also expect failure if an algorithm is not advertized if sigalg not in cr_sigalgs: expectPass = False conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) # force sigalg node = node.add_child(CertificateVerifyGenerator(private_key, msg_alg= sigalg)) node = node.add_child(FinishedGenerator()) result = "works" # only signatures of matching certificate type should work if expectPass: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child(AlertGenerator( AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() else: node = node.add_child(ExpectAlert( AlertLevel.fatal, AlertDescription.illegal_parameter)) node.add_child(ExpectClose()) result = "is refused" conversations["check {0} signature {1}".format( SignatureScheme.toStr(sigalg), result)] = conversation # verify that rsa-pss signatures with empty, too short or too long # salt fail msgalg = sigalg_select("rsa_pss", hashalgs, cr_sigalgs, certType) hash_name = SignatureScheme.getHash(SignatureScheme.toRepr(msgalg)) digest_len = getattr(tlshashlib, hash_name)().digest_size for saltlen in (0, digest_len - 1, digest_len + 1): conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) # force salt length node = node.add_child(CertificateVerifyGenerator( private_key, rsa_pss_salt_len=saltlen)) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectAlert( AlertLevel.fatal, AlertDescription.decrypt_error)) node.add_child(ExpectClose()) conversations["check signature with salt length {0}".format( saltlen)] = conversation # verify that a rsa-pkcs1 signature in a rsa-pss ID envelope fails sigalg = sigalg_select("rsa_pkcs1", hashalgs) msgalg = sigalg_select("rsa_pss", hashalgs, cr_sigalgs, certType) conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(CertificateVerifyGenerator( private_key, sig_alg=sigalg, msg_alg=msgalg)) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectAlert( AlertLevel.fatal, AlertDescription.decrypt_error)) node.add_child(ExpectClose()) scheme = SignatureScheme.toRepr(sigalg) conversations["check pkcs1 signature with rsa-pss envelope fails"] = \ conversation # verify that a rsa-pss signature with mismatched message hash fails msgalg = sigalg_select("rsa_pss", hashalgs, cr_sigalgs, certType) # choose a similar scheme with just a different hash, doesn't need to be # a server supported sigalg hash_name = SignatureScheme.getHash(SignatureScheme.toRepr(msgalg)) _hashalgs = [x for x in hashalgs if x != hash_name] sigalg = sigalg_select("rsa_pss", _hashalgs, cert_type=certType) conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(CertificateVerifyGenerator( private_key, sig_alg=sigalg, msg_alg=msgalg)) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectAlert( AlertLevel.fatal, AlertDescription.decrypt_error)) node.add_child(ExpectClose()) conversations["check rsa-pss signature with mismatched hash fails"] = \ conversation # verify that a rsa-pss signature with mismatched MGF1 hash fails sigalg = sigalg_select("rsa_pss", hashalgs, cr_sigalgs, certType) # choose a different hash to cause mismtach hash_name = SignatureScheme.getHash(SignatureScheme.toRepr(msgalg)) mgf1_hash = [x for x in hashalgs if x != hash_name][0] conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(CertificateVerifyGenerator( private_key, mgf1_hash=mgf1_hash, msg_alg=sigalg)) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectAlert( AlertLevel.fatal, AlertDescription.decrypt_error)) node.add_child(ExpectClose()) conversations["check rsa-pss signature with mismatched mgf1 fails"] = \ conversation # check that fuzzed signatures are rejected for pos in range(numBytes(private_key.n)): for xor in [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]: conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {} groups = [GroupName.secp256r1] ext[ExtensionType.key_share] = key_share_ext_gen(groups) ext[ExtensionType.supported_versions] = \ SupportedVersionsExtension().create([(3, 4), (3, 3)]) ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator( ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(CertificateVerifyGenerator( private_key, padding_xors={pos:xor})) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectAlert( AlertLevel.fatal, AlertDescription.decrypt_error)) node.add_child(ExpectClose()) scheme = SignatureScheme.toRepr(sigalg) conversations_long["check that fuzzed signatures are rejected." + " Malformed {0} - xor {1} at {2}".format( certType, hex(xor), pos)] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations_long) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] short_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] long_tests = list(conversations_long.items()) long_sampled_tests = sample(long_tests, min(num_limit, len(long_tests))) regular_tests = sample(long_sampled_tests + short_tests, len(long_sampled_tests) + len(short_tests)) ordered_tests = chain(sanity_tests, regular_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n" .format(expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test to verify that server properly accepts or refuses") print("signatures in TLS1.3; PKCS1 signatures are always refused.") print("Other signatures are accepted or refused accordingly to") print("the certificate type provided ('rsa' vs 'rsa-pss').\n") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(regular_tests) + 2*len(sanity_tests))) print("SKIP: {0}".format(len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed ,key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): http = False conversations = {} # check if server works at all conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["sanity"] = conversation # check if server works with SHA384 PRF ciphersuite conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["sanity sha384 prf"] = conversation # check if server works at all (TLSv1.1) conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, version=(3, 2), extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello( version=(3, 2), extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["sanity TLSv1.1"] = conversation # check if server supports extended master secret conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["extended master secret"] = conversation # check if server supports extended master secret with SHA384 PRF conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["extended master secret w/SHA384 PRF"] = conversation # check if server supports extended master secret conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, version=(3, 2), extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( version=(3, 2), extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["extended master secret in TLSv1.1"] = conversation # check if server doesn't default to extended master secret conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator( extended_master_secret=True)) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectAlert(level=AlertLevel.fatal)) node = node.add_child(ExpectClose()) node = node.add_child(Close()) conversations["no EMS by default"] = conversation # check if server uses EMS for resumed connections conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) close = ExpectClose() node.next_sibling = close node = node.add_child(ExpectClose()) node = node.add_child(Close()) node = node.add_child(Connect("localhost", 4433)) close.add_child(node) node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ResetRenegotiationInfo()) node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None}, resume=True)) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["EMS with session resume"] = conversation # check if server uses EMS for resumed connections and SHA384 PRF conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) close = ExpectClose() node.next_sibling = close node = node.add_child(ExpectClose()) node = node.add_child(Close()) node = node.add_child(Connect("localhost", 4433)) close.add_child(node) node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ResetRenegotiationInfo()) node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None}, resume=True)) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.add_child(Close()) conversations["EMS with session resume and SHA384 PRF"] = conversation # check if server aborts session resume without EMS extension conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) close = ExpectClose() node.next_sibling = close node = node.add_child(ExpectClose()) node = node.add_child(Close()) node = node.add_child(Connect("localhost", 4433)) close.add_child(node) node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ResetRenegotiationInfo()) node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(Close()) conversations["EMS with session resume without extension"] = conversation # check if server does full handshake on resumed session without EMS conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) close = ExpectClose() node.next_sibling = close node = node.add_child(ExpectClose()) node = node.add_child(Close()) node = node.add_child(Connect("localhost", 4433)) close.add_child(node) node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ResetRenegotiationInfo()) node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None}, resume=False)) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node.next_sibling.add_child(Close()) node.add_child(Close()) conversations["resume non-EMS session with EMS extension"] = \ conversation # EMS with renegotiation conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ClientHelloGenerator( ciphers, session_id=bytearray(0), # do not resume extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(Close()) conversations["extended master secret with renegotiation"] = conversation # renegotiation in non-EMS session conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ClientHelloGenerator( ciphers, session_id=bytearray(0), # do not resume extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(Close()) conversations["renegotiate with EMS in session without EMS"] = conversation # renegotiation of non-EMS session in EMS session conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator( ciphers, extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ClientHelloGenerator( ciphers, session_id=bytearray(0), # do not resume extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectServerHello( extensions={ExtensionType.renegotiation_info:None})) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if http: node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(Close()) conversations["renegotiate without EMS in session with EMS"] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # skip Client Hello conversation = Connect(host, port) node = conversation node = node.add_child( ClientKeyExchangeGenerator( cipher=CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, version=(3, 3), encrypted_premaster=bytearray(b'\xff' * 256))) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node = node.add_child(ExpectClose()) conversations["skip Client Hello"] = conversation # skip client key exchange conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node = node.add_child(ExpectClose()) conversations["skip Client Key Exchange"] = conversation # skip Change Cipher Spec conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node = node.add_child(ExpectClose()) conversations["skip Change Cipher Spec"] = conversation # skip Finished conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node = node.add_child(ExpectClose()) conversations["skip Finished"] = conversation # run the conversation good = 0 bad = 0 failed = [] # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], filter(lambda x: x[0] != 'sanity', conversations.items()), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK") else: bad += 1 failed.append(c_name) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): """ Test if the server will not accept cipher forcing from client client forces 3DES """ conversations = {} host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = str() argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:e:n:x:X:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) for prot_vers, proto_name in { (0, 2): "SSLv2", (3, 0): "SSLv3", (3, 1): "TLSv1.0" }.items(): for cipher_id, cipher_name in { CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5: "DES-CBC3-MD5" }.items(): # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [ CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_IDEA_128_CBC_WITH_MD5, CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5 ] node = node.add_child( ClientHelloGenerator(ciphers, version=prot_vers, ssl2=True)) # we can get a ServerHello with no ciphers: node = node.add_child(ExpectServerHello2()) # or we can get an error stright away, and connection closure node.next_sibling = ExpectSSL2Alert(SSL2ErrorDescription.no_cipher) node.next_sibling.add_child(ExpectClose()) alternative = node.next_sibling # or the server may close the connection right away (likely in # case SSLv2 is completely disabled) alternative.next_sibling = ExpectClose() alternative = alternative.next_sibling # or finally, we can get a TLS Alert message alternative.next_sibling = ExpectAlert() alternative.next_sibling.add_child(ExpectClose()) # in case we got ServerHello, try to force one of the ciphers node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) # it should result in error node = node.add_child(ExpectSSL2Alert()) # or connection close node.next_sibling = ExpectClose() # in case of error, we expect the server to close connection node.add_child(ExpectClose()) conversations["Connect with {1} {0}".format( cipher_name, proto_name)] = conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) sampled_tests = sample(list(conversations.items()), len(conversations)) for c_name, conversation in sampled_tests: if c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(conversation) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) print("") res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Note: SSLv2 was officially deprecated (MUST NOT use) in 2011, see") print(" RFC 6176.") print( " If one or more of the tests fails because of error in form of") print("") print(" Unexpected message from peer: Handshake()") print("") print(" With any number inside parethensis, and the server is") print(" configured to not support SSLv2, it means it most") print(" likely is vulnerable to CVE-2015-3197.") print(" In case it's a RC4 or 3DES cipher, you may verify that it") print(" really supports it using:") print(" test-sslv2-connection.py") print("") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): """Test if the server supports export grade SSLv2 ciphers""" conversations = {} host = "localhost" port = 4433 argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) for prot_vers, proto_name in { (0, 2):"SSLv2", (3, 0):"SSLv3", (3, 1):"TLSv1.0" }.items(): for cipher_id, cipher_name in { CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5:"EXP-RC4-MD5", CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5: "EXP-RC2-CBC-MD5" }.items(): # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_IDEA_128_CBC_WITH_MD5, CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5] node = node.add_child(ClientHelloGenerator(ciphers, version=prot_vers, ssl2=True)) # we can get a ServerHello with no ciphers: node = node.add_child(ExpectServerHello2()) # or we can get an error stright away, and connection closure node.next_sibling = ExpectSSL2Alert(SSL2ErrorDescription.no_cipher) node.next_sibling.add_child(ExpectClose()) alternative = node.next_sibling # or the server may close the connection right away (likely in # case SSLv2 is completely disabled) alternative.next_sibling = ExpectClose() alternative = alternative.next_sibling # or finally, we can get a TLS Alert message alternative.next_sibling = ExpectAlert() alternative.next_sibling.add_child(ExpectClose()) # in case we got ServerHello, try to force one of the ciphers node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) # it should result in error node = node.add_child(ExpectSSL2Alert()) # or connection close node.next_sibling = ExpectClose() # in case of error, we expect the server to close connection node = node.add_child(ExpectClose()) conversations["Connect with {1} {0}" .format(cipher_name, proto_name)] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("Note: SSLv2 was officially deprecated (MUST NOT use) in 2011, see") print(" RFC 6176.") print(" If one or more of the tests fails because of error in form of") print("") print(" Unexpected message from peer: Handshake()") print("") print(" With any number inside parethensis, and the server is") print(" configured to not support SSLv2, it means it most") print(" likely is vulnerable to CVE-2015-3197 and CVE-2016-0800.") print(" In case it's a RC4 or 3DES cipher, you may verify that it") print(" really supports it using:") print(" test-sslv2-connection.py") print("") print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """check if server handles malformed server name indication extension""" host = "localhost" hostname = "localhost" port = 4433 run_exclude = set() sni_fatal = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:", ["help", "sni=", "sni-fatal"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '--help': help_msg() sys.exit(0) elif opt == '--sni': hostname = arg elif opt == '--sni-fatal': sni_fatal = True else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} # sanity check without SNI conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert(AlertLevel.warning, AlertDescription.close_notify) node.next_sibling.add_child(ExpectClose()) conversations["sanity"] = conversation # sanity check SNI conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } sni = SNIExtension().create(bytearray(hostname, 'utf-8')) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert(AlertLevel.warning, AlertDescription.close_notify) node.next_sibling.add_child(ExpectClose()) conversations["Sanity check, SNI"] = conversation # empty SNI extension conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } sni = TLSExtension(extType=ExtensionType.server_name).create(bytearray(0)) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.add_child(ExpectClose()) conversations["Empty SNI extension"] = conversation # empty host list conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } sni = SNIExtension().create(serverNames=[]) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.add_child(ExpectClose()) conversations["Empty host list in SNI extension"] = conversation # empty host name conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } sni = SNIExtension().create(hostNames=[bytearray(0)]) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.add_child(ExpectClose()) conversations["Empty hostname in SNI extension"] = conversation # trailing data in extension conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } payload = bytearray(b'\x00\x04' # overall length b'\x00' # type - host_name b'\x00\x01' # length of host name b'e' # host name b'x' # trailing data ) sni = TLSExtension(extType=ExtensionType.server_name).create(payload) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.add_child(ExpectClose()) conversations["Trailing data in extension"] = conversation # incorrect host name conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } sni = SNIExtension().create( bytearray(b'www.') + bytearray(hostname, 'utf-8')) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) if sni_fatal: node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.unrecognized_name)) node = node.add_child(ExpectClose()) else: node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.unrecognized_name)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert(AlertLevel.warning, AlertDescription.close_notify) node.next_sibling.add_child(ExpectClose()) conversations["incorrect SNI"] = conversation # SNI name with NULL conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } # names MUST be valid DNS host names sni = SNIExtension().create( bytearray(hostname[:-1], 'utf-8') + bytearray(b'\x00') + bytearray(hostname[-1:], 'utf-8')) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) node = node.add_child(ExpectClose()) conversations["SNI name with NULL"] = conversation # SNI name with special character conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } # names MUST be valid DNS host names sni = SNIExtension().create( bytearray(hostname[:-1], 'utf-8') + bytearray(b'\x07') + bytearray(hostname[-1:], 'utf-8')) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) node = node.add_child(ExpectClose()) conversations["SNI name with BEL"] = conversation # SNI name with UTF-8 character conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } # names MUST be valid DNS host names sni = SNIExtension().create( bytearray(hostname[:-1], 'utf-8') + bytearray(b'\xc4\x85') + bytearray(hostname[-1:], 'utf-8')) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) node = node.add_child(ExpectClose()) conversations["SNI name with UTF-8"] = conversation conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } # names MUST be valid DNS host names sni = SNIExtension().create( bytearray(hostname, 'utf-8') + bytearray(b'\x1b[31mBAD\x1b[0;37m')) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) node = node.add_child(ExpectClose()) conversations["SNI name with ANSI color escapes code"] = conversation # malformed extension conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = { ExtensionType.server_name: lambda _: TLSExtension().create(0, bytearray(b'\xff' * 4)) } node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["malformed overall length"] = conversation # multiple names in SNI conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } # RFC 6066 client MUST NOT send two names of the same type sni = SNIExtension().create(hostNames=[ bytearray(hostname, 'utf-8'), bytearray(b'www.') + bytearray(hostname, 'utf-8') ]) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) node = node.add_child(ExpectClose()) conversations[ "multiple host_names in SNI, RFC 6066 compliance"] = conversation # multiple types in SNI conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } names = [ SNIExtension.ServerName(NameType.host_name, bytearray(hostname, 'utf-8')), # some unknown SNI type, should be ignored by server SNIExtension.ServerName(NameType.host_name + 1, bytearray(range(0, 24))) ] sni = SNIExtension().create(serverNames=names) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert(AlertLevel.warning, AlertDescription.close_notify) node.next_sibling.add_child(ExpectClose()) conversations["multiple types in SNI, host_name first"] = conversation # multiple types in SNI, host_name last conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1'] ]), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } names = [ # some unknown SNI type, should be ignored by server SNIExtension.ServerName(NameType.host_name + 1, bytearray(range(0, 24))), # actual SNI payload SNIExtension.ServerName(NameType.host_name, bytearray(hostname, 'utf-8')) ] sni = SNIExtension().create(serverNames=names) ext[ExtensionType.server_name] = sni node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert(AlertLevel.warning, AlertDescription.close_notify) node.next_sibling.add_child(ExpectClose()) # hangs gnutls-serv conversations["multiple types in SNI, host_name last"] = conversation # run the conversation good = 0 bad = 0 failed = [] # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], filter(lambda x: x[0] != 'sanity', conversations.items()), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("SNI extension test version 3") print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): """check if atypical padding is accepted by server""" conversations = {} conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) text = b"GET / HTTP/1.0\nX-bad: aaaa\n\n" hmac_tag_length = 20 block_size = 16 # make sure that padding has full blocks to work with assert (len(text) + hmac_tag_length) % block_size == 0 node = node.add_child(fuzz_padding(ApplicationDataGenerator(text), min_length=255)) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["256 bytes of padding"] = \ conversation # run the conversation good = 0 bad = 0 for conversation_name in conversations: conversation = conversations[conversation_name] print(conversation_name + "...") runner = Runner(conversation) res = True #because we don't want to abort the testing and we are reporting #the errors to the user, using a bare except is OK #pylint: disable=bare-except try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False #pylint: enable=bare-except if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """check if incorrect padding is rejected by server""" host = "localhost" port = 4433 num_limit = 800 run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest()) fork = node node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) # handle servers which ask for client certificates fork.next_sibling = ExpectServerHelloDone() join = ClientKeyExchangeGenerator() fork.next_sibling.add_child(join) node = node.add_child(join) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\r\n\r\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["sanity"] = \ conversation # block size is 16 bytes for AES_128, 2**14 is the TLS protocol max for data in structured_random_iter(num_limit, min_length=16, max_length=2**14, step=16): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest()) fork = node node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) # handle servers which ask for client certificates fork.next_sibling = ExpectServerHelloDone() join = ClientKeyExchangeGenerator() fork.next_sibling.add_child(join) node = node.add_child(join) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( replace_plaintext( ApplicationDataGenerator( b"I'm ignored, only type is important"), data.data)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["encrypted plaintext of {0}".format(data)] = \ conversation # run the conversation good = 0 bad = 0 failed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], islice( filter(lambda x: x[0] != 'sanity', conversations.items()), num_limit), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except Exception: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) failed_sorted = sorted(failed, key=natural_sort_keys) print(" {0}".format('\n '.join(repr(i) for i in failed_sorted))) if bad > 0: sys.exit(1)
def main(): """check if obsolete signature algorithm is rejected by server""" conversations = {} hostname = "localhost" port = 4433 argv = sys.argv[1:] if len(argv) != 4: raise ValueError("You need to specify key (-k file.pem) and " "certificate (-c file.pem)") opts, argv = getopt.getopt(argv, "k:c:") for opt, arg in opts: if opt == '-k': text_key = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_key = str(text_key, 'utf-8') private_key = parsePEMKey(text_key, private=True) if opt == '-c': text_cert = open(arg, 'rb').read() if sys.version_info[0] >= 3: text_cert = str(text_cert, 'utf-8') cert = X509() cert.parse(text_cert) if not private_key: raise ValueError("Specify private key file using -k") if not cert: raise ValueError("Specify certificate file using -c") for md in ['sha1', 'sha256', 'sha384', 'sha512']: conversation = Connect(hostname, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] ext = {ExtensionType.signature_algorithms : SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1', 'md5']])} node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(CertificateVerifyGenerator( private_key, sig_type=(getattr(HashAlgorithm, md), SignatureAlgorithm.rsa))) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ApplicationDataGenerator(b"GET / HTTP/1.0\n\n")) node = node.add_child(ExpectApplicationData()) node = node.add_child(AlertGenerator(AlertDescription.close_notify)) node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["check " + md] = conversation # run the conversation good = 0 bad = 0 print("Certificate Verify test version 2") for conversation_name in conversations: conversation = conversations[conversation_name] print(conversation_name + "...") runner = Runner(conversation) res = True #because we don't want to abort the testing and we are reporting #the errors to the user, using a bare except is OK #pylint: disable=bare-except try: runner.run() except: print("Error while processing") print(traceback.format_exc()) res = False #pylint: enable=bare-except if res: good+=1 print("OK") else: bad+=1 print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} # basic connection conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # ensure that the server sends at least one NST always node = node.add_child(ExpectNewSessionTicket()) # but multiple ones are OK too cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node.add_child(ExpectClose()) conversations["sanity"] = conversation # resume a session conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # ensure that the server sends at least one NST always node = node.add_child(ExpectNewSessionTicket()) # but multiple ones are OK too cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) # server can close connection without sending alert close = ExpectClose() node.next_sibling = close node = node.add_child(close) node = node.add_child(Close()) node = node.add_child(Connect(host, port)) # start the second handshake node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ResetRenegotiationInfo()) ext = OrderedDict(ext) ext[ExtensionType.pre_shared_key] = psk_session_ext_gen() mods = [] mods.append(psk_ext_updater()) node = node.add_child( ClientHelloGenerator(ciphers, extensions=ext, modifiers=mods)) ext = {} ext[ExtensionType.supported_versions] = srv_ext_handler_supp_vers ext[ExtensionType.pre_shared_key] = gen_srv_ext_handler_psk() ext[ExtensionType.key_share] = srv_ext_handler_key_share node = node.add_child(ExpectServerHello(extensions=ext)) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # ensure that the server sends at least one NST always node = node.add_child(ExpectNewSessionTicket()) # but multiple ones are OK too cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() node.add_child(ExpectClose()) conversations["session resumption"] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, min(num_limit, len(regular_tests))) ordered_tests = chain(sanity_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Basic session resumption test with TLS 1.3 server\n") print("version: {0}\n".format(version)) print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests) + 2 * len(sanity_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)