def test_is_match_with_unmatching_content_type(self): exp = ExpectServerHelloDone() msg = Message(ContentType.application_data, bytearray([HandshakeType.server_hello_done])) self.assertFalse(exp.is_match(msg))
def test_is_match(self): exp = ExpectServerHelloDone() msg = Message(ContentType.handshake, bytearray([HandshakeType.server_hello_done])) self.assertTrue(exp.is_match(msg))
def test_is_match_with_unmatching_handshake_type(self): exp = ExpectServerHelloDone() msg = Message(ContentType.handshake, bytearray([HandshakeType.client_hello])) self.assertFalse(exp.is_match(msg))
def add_handshake_conversation(conversations, host, port, cipher, dhe, data): conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) else: ext = None ciphers = [cipher, 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(replace_plaintext( FinishedGenerator(), data.data)) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node = node.add_child(ExpectClose()) conversations["encrypted Handshake plaintext of {0}".format(data)] = \ conversation
def test___init__(self): exp = ExpectServerHelloDone() self.assertIsNotNone(exp) self.assertTrue(exp.is_expect()) self.assertFalse(exp.is_command()) self.assertFalse(exp.is_generator())
def __iter__(self): """ @return: iterator of the test cases available """ # sanity check if we can connect with server conv = Conversation() conv.messages.append(('clnt', Connect(\ self.fingerprint.ip, self.fingerprint.port))) conv.messages.append(('clnt', ClientHelloGenerator(\ ciphers=[CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA]))) conv.messages.append(('srv', ExpectServerHello())) conv.messages.append(('srv', ExpectCertificate())) conv.messages.append(('srv', ExpectServerHelloDone())) conv.messages.append(('clnt', ClientKeyExchangeGenerator())) conv.messages.append(('clnt', ChangeCipherSpecGenerator())) conv.messages.append(('clnt', FinishedGenerator())) conv.messages.append(('srv', ExpectChangeCipherSpec())) conv.messages.append(('srv', ExpectFinished())) conv.messages.append(('clnt', AlertGenerator())) conv.messages.append(('clnt', Close())) yield conv # try to interleave application_data with handshake during renegotiation # reproducer for https://rt.openssl.org/Ticket/Display.html?id=3712 conv = Conversation() conv.record_version = (3, 3) conv.messages.append(('clnt', Connect(\ self.fingerprint.ip, self.fingerprint.port))) # first handshake conv.messages.append(('clnt', ClientHelloGenerator(\ ciphers=[CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA]))) conv.messages.append(('srv', ExpectServerHello())) conv.messages.append(('srv', ExpectCertificate())) conv.messages.append(('srv', ExpectServerHelloDone())) conv.messages.append(('clnt', ClientKeyExchangeGenerator())) conv.messages.append(('clnt', ChangeCipherSpecGenerator())) conv.messages.append(('clnt', FinishedGenerator())) conv.messages.append(('srv', ExpectChangeCipherSpec())) conv.messages.append(('srv', ExpectFinished())) # renegotiation conv.messages.append(('clnt', ClientHelloGenerator(\ ciphers=[CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA]))) conv.messages.append(('srv', ExpectServerHello())) conv.messages.append(('srv', ExpectCertificate())) conv.messages.append(('srv', ExpectServerHelloDone())) conv.messages.append(('clnt', ApplicationDataGenerator('Hello!'))) conv.messages.append(('clnt', ClientKeyExchangeGenerator())) conv.messages.append(('clnt', ChangeCipherSpecGenerator())) conv.messages.append(('clnt', FinishedGenerator())) conv.messages.append(('srv', ExpectChangeCipherSpec())) conv.messages.append(('srv', ExpectFinished())) # connection close conv.messages.append(('clnt', AlertGenerator())) conv.messages.append(('clnt', Close())) yield conv
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 add_app_data_conversation(conversations, host, port, cipher, dhe, data): conversation = Connect(host, port) node = conversation if dhe: ext = {} add_dhe_extensions(ext) else: ext = None ciphers = [cipher, 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()) # handle servers that ask for client certificates node = node.add_child(ExpectCertificateRequest()) fork = node node = node.add_child(ExpectServerHelloDone()) node = node.add_child(CertificateGenerator()) # handle servers that don't ask for client certificates fork.next_sibling = ExpectServerHelloDone() # join both paths 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 Application Data plaintext of {0}" .format(data)] = \ conversation
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(): """Check if EMS with client certificates is supported""" hostname = "localhost" port = 4433 run_exclude = set() sigalgs = [(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': hostname = 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']])} ext[ExtensionType.extended_master_secret] = None node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None} node = node.add_child(ExpectServerHello(version=(3, 3), extensions=ext)) 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']])} ext[ExtensionType.extended_master_secret] = None node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None} node = node.add_child(ExpectServerHello(version=(3, 3), extensions=ext)) 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 # resume session with 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']])} ext[ExtensionType.extended_master_secret] = None node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None} node = node.add_child(ExpectServerHello(version=(3, 3), extensions=ext)) 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(ExpectAlert()) close = ExpectClose() node.next_sibling = close node = node.add_child(ExpectClose()) node = node.add_child(Close()) node = node.add_child(Connect(hostname, port)) close.add_child(node) node = node.add_child(ResetHandshakeHashes()) node = node.add_child(ResetRenegotiationInfo()) ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.signature_algorithms : SignatureAlgorithmsExtension().create([ (getattr(HashAlgorithm, x), SignatureAlgorithm.rsa) for x in ['sha512', 'sha384', 'sha256', 'sha224', 'sha1', 'md5']])} ext[ExtensionType.extended_master_secret] = None ext[ExtensionType.renegotiation_info] = None node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info:None, ExtensionType.extended_master_secret:None} node = node.add_child(ExpectServerHello(version=(3, 3), extensions=ext, resume=True)) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) 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.add_child(Close()) conversations["resume with certificate and EMS"] = 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 supports extended master secret with ") print("client certificates.\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 run_exclude = set() http = True argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:", ["help", "no-http"]) 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 == '--no-http': http = False else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} # check if server works at all conversation = Connect(host, port) 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\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(host, port) 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\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(host, port) 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\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(host, port) 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: AutoEmptyExtension() })) 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.add_child(Close()) conversations["extended master secret"] = conversation # check if server supports extended master secret with ECDHE conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA] node = node.add_child( ClientHelloGenerator(ciphers, extensions={ ExtensionType.renegotiation_info: None, ExtensionType.extended_master_secret: AutoEmptyExtension(), ExtensionType.supported_groups: SupportedGroupsExtension().create( [GroupName.secp256r1]) })) node = node.add_child( ExpectServerHello( extensions={ ExtensionType.renegotiation_info: None, ExtensionType.extended_master_secret: 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()) 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.add_child(Close()) conversations["extended master secret w/ECDHE"] = conversation # check if server supports extended master secret with DHE 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, ExtensionType.extended_master_secret: AutoEmptyExtension() })) node = node.add_child( ExpectServerHello( extensions={ ExtensionType.renegotiation_info: None, ExtensionType.extended_master_secret: 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()) 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.add_child(Close()) conversations["extended master secret w/DHE"] = conversation # check if server rejects malformed EMS extension # (extension must be empty) conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} ext[ExtensionType.extended_master_secret] = \ TLSExtension(extType=ExtensionType.extended_master_secret).\ create(bytearray(b'\x00')) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.next_sibling = ExpectClose() conversations["malformed extended master secret ext"] = conversation # check if server supports extended master secret with SHA384 PRF conversation = Connect(host, port) 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: AutoEmptyExtension() })) 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.add_child(Close()) conversations["extended master secret w/SHA384 PRF"] = conversation # check if server supports extended master secret conversation = Connect(host, port) 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: AutoEmptyExtension() })) 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\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(host, port) 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(AlertLevel.fatal, AlertDescription.bad_record_mac)) 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(host, port) 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: AutoEmptyExtension() })) 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(host, port)) 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: AutoEmptyExtension() })) 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\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(host, port) 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: AutoEmptyExtension() })) 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(host, port)) 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: AutoEmptyExtension() })) 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\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(host, port) 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: AutoEmptyExtension() })) 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(host, port)) 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(host, port) 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(host, port)) 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: AutoEmptyExtension() })) 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\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(host, port) 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: AutoEmptyExtension() })) 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: AutoEmptyExtension() })) 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(host, port) 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: AutoEmptyExtension() })) 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(host, port) 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: AutoEmptyExtension() })) 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 # 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 throughout sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] shuffled_tests = sample(regular_tests, len(regular_tests)) ordered_tests = chain(sanity_tests, shuffled_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() dhe = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e: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 == '-d': 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 ext = None if dhe: groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext = { ExtensionType.supported_groups: SupportedGroupsExtension().create(groups), ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(RSA_SIG_ALL), 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: 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 /?Renegotiation_Test=tlsfuzzer 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 # renegotiation conversation = Connect(host, port) node = conversation ext = {ExtensionType.renegotiation_info: None} if dhe: 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info: None} node = node.add_child(ExpectServerHello(extensions=ext)) 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()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) ext = {ExtensionType.renegotiation_info: None} if dhe: 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) node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), extensions=ext)) ext = {ExtensionType.renegotiation_info: None} node = node.add_child(ExpectServerHello(extensions=ext)) 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()) # send GET request node = node.add_child( ApplicationDataGenerator( bytearray(b"GET /?Renegotiation_Test=tlsfuzzer HTTP/1.0\r\n"))) node = node.add_child(ApplicationDataGenerator(bytearray(b'\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[ "secure renegotiation with GET after 2nd handshake"] = conversation # renegotiation conversation = Connect(host, port) node = conversation ext = {ExtensionType.renegotiation_info: None} if dhe: 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info: None} node = node.add_child(ExpectServerHello(extensions=ext)) 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()) # send incomplete GET request node = node.add_child( ApplicationDataGenerator( bytearray(b"GET /?Renegotiation_Test=tlsfuzzer HTTP/1.0\r\n"))) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) ext = {ExtensionType.renegotiation_info: None} if dhe: 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) node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), extensions=ext)) ext = {ExtensionType.renegotiation_info: None} node = node.add_child(ExpectServerHello(extensions=ext)) 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()) # finish the GET request node = node.add_child(ApplicationDataGenerator(bytearray(b'\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["secure renegotiation with incomplete GET"] = conversation # insecure renegotiation conversation = Connect(host, port) node = conversation ext = None if dhe: groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext = { ExtensionType.supported_groups: SupportedGroupsExtension().create(groups), ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(RSA_SIG_ALL), 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] 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()) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) ext = None if dhe: groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext = { ExtensionType.supported_groups: SupportedGroupsExtension().create(groups), ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(RSA_SIG_ALL), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), 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()) # send GET request node = node.add_child( ApplicationDataGenerator( bytearray(b"GET /?Renegotiation_Test=tlsfuzzer HTTP/1.0\r\n"))) node = node.add_child(ApplicationDataGenerator(bytearray(b'\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[ "insecure (legacy) renegotiation with GET after 2nd handshake"] = conversation # insecure renegotiation conversation = Connect(host, port) node = conversation ext = None if dhe: groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext = { ExtensionType.supported_groups: SupportedGroupsExtension().create(groups), ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(RSA_SIG_ALL), 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] 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()) # send incomplete GET request node = node.add_child( ApplicationDataGenerator( bytearray(b"GET /?Renegotiation_Test=tlsfuzzer HTTP/1.0\r\n"))) # 2nd handshake node = node.add_child(ResetHandshakeHashes()) ext = None if dhe: groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext = { ExtensionType.supported_groups: SupportedGroupsExtension().create(groups), ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(RSA_SIG_ALL), ExtensionType.signature_algorithms_cert: SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) } node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), 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()) # finish the GET request node = node.add_child(ApplicationDataGenerator(bytearray(b'\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[ "insecure (legacy) renegotiation with incomplete GET"] = conversation # sending both SCSV and renegotiation_info: cold, then renegotiated conversation = Connect(host, port) node = conversation # Sending both is NOT RECOMMENDED, though valid, for the first handshake... ext = {ExtensionType.renegotiation_info: None} if dhe: 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: ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info: None} node = node.add_child(ExpectServerHello(extensions=ext)) 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()) # ... but not for the second handshake node = node.add_child(ResetHandshakeHashes()) ext = {ExtensionType.renegotiation_info: None} if dhe: 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: ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectClose()) conversations[ "sending both SCSV and renegotiation_info in renegotiated handshake"] = conversation # sending both SCSV and renegotiation_info: cold, then renegotiated+resumed conversation = Connect(host, port) node = conversation # Sending both is NOT RECOMMENDED, though valid, for the first handshake... ext = {ExtensionType.renegotiation_info: None} if dhe: 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: ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = {ExtensionType.renegotiation_info: None} node = node.add_child(ExpectServerHello(extensions=ext)) 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()) # ... but not for the second handshake node = node.add_child(ResetHandshakeHashes()) ext = {ExtensionType.renegotiation_info: None} if dhe: 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: 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( ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectClose()) conversations[ "sending both SCSV and renegotiation_info in renegotiation+resumption"] = conversation # non-empty initial renegotiation_info extension (with SCSV) conversation = Connect(host, port) node = conversation ext = { ExtensionType.renegotiation_info: RenegotiationInfoExtension().create(bytearray(b'abc')) } if dhe: 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: 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( ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectClose()) conversations[ "non-empty initial renegotiation_info extension (with SCSV)"] = conversation # non-empty initial renegotiation_info extension (without SCSV) conversation = Connect(host, port) node = conversation ext = { ExtensionType.renegotiation_info: RenegotiationInfoExtension().create(bytearray(b'abc')) } if dhe: 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectClose()) conversations[ "non-empty initial renegotiation_info extension (without SCSV)"] = 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 if the server supports insecure (legacy) renegotiation") 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 malformed signatures in Certificate Verify are rejected""" host = "localhost" port = 4433 num_limit = None run_exclude = set() private_key = None cert = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n: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 == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) 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 not private_key: raise ValueError("Specify private key file using -k") if not cert: raise ValueError("Specify certificate file using -c") if args: run_only = set(args) else: run_only = None conversations = {} # sanity check for Client Certificates sanity_hash_alg = ("sha1", "sha256") for hash_alg in sanity_hash_alg: 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', '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()) sig_type = (getattr(HashAlgorithm, hash_alg), SignatureAlgorithm.rsa) node = node.add_child(CertificateVerifyGenerator(private_key, msg_alg=sig_type )) 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 - {0}".format(hash_alg)] = conversation # place SHA-1 sig with SHA-256 indicator 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', '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()) sig_type = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) msg_type = (HashAlgorithm.sha256, SignatureAlgorithm.rsa) node = node.add_child(CertificateVerifyGenerator(private_key, msg_alg=msg_type, sig_alg=sig_type )) # the other side can close connection right away, add options to handle it node.next_sibling = ExpectClose() node = node.add_child(ChangeCipherSpecGenerator()) node.next_sibling = ExpectClose() node = node.add_child(FinishedGenerator()) node.next_sibling = ExpectClose() # we expect closure or Alert and then closure of socket node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["SHA-1 signature in SHA-256 envelope"] = conversation # because the TLSv1.1 signatures are concatenation of MD5 and SHA1 # implementation that just checks the hash, without verifying the Hash # Info structure in signature, will accept a TLSv1.1 signature # in a TLSv1.2 SHA-1 envelope 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', '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()) msg_alg = (HashAlgorithm.sha1, SignatureAlgorithm.rsa) node = node.add_child(CertificateVerifyGenerator(private_key, msg_alg=msg_alg, sig_version=(3, 2) )) # the other side can close connection right away, add options to handle it node.next_sibling = ExpectClose() node = node.add_child(ChangeCipherSpecGenerator()) node.next_sibling = ExpectClose() node = node.add_child(FinishedGenerator()) node.next_sibling = ExpectClose() # we expect closure or Alert and then closure of socket node = node.add_child(ExpectClose()) node.next_sibling = ExpectAlert() node.next_sibling.add_child(ExpectClose()) conversations["TLSv1.1 signature in SHA-1 TLSv1.2 envelope"] = 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_tests = [] for hash_alg in sanity_hash_alg: sanity_test_name = 'sanity - {0}'.format(hash_alg) sanity_tests.append((sanity_test_name, conversations[sanity_test_name])) ordered_tests = chain(sanity_tests, islice(filter(lambda x: not 'sanity' in x[0], conversations.items()), num_limit), 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("CertificateVerify malformed signatures 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(): hostname = "localhost" port = 4433 number_of_alerts = 4 run_exclude = set() alert_level = AlertLevel.fatal alert_description = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:", ["help", "alert-level=", "alert-description="]) 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 == '-n': number_of_alerts = int(arg) elif opt == '--help': help_msg() sys.exit(0) elif opt == '--alert-level': alert_level = flexible_getattr(arg, AlertLevel) elif opt == '--alert-description': alert_description = flexible_getattr(arg, AlertDescription) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(hostname, port, version=(3, 3)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers)) for _ in range(number_of_alerts): # sending alerts during handshake node = node.add_child(AlertGenerator( # alert description: 46, 41, 43 AlertLevel.warning, AlertDescription.unsupported_certificate)) 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(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() conversations["SSL Death Alert without getting alert"] = conversation conversation = Connect(hostname, port, version=(3, 3)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers)) for _ in range(number_of_alerts+1): node = node.add_child(AlertGenerator( AlertLevel.warning, AlertDescription.unsupported_certificate)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ExpectAlert(alert_level, alert_description)) node = node.add_child(ExpectClose()) conversations["SSL Death Alert with getting alert"] = conversation # run the conversation good = 0 bad = 0 failed = [] shuffled_tests = sample(list(conversations.items()), len(conversations)) for conversation_name, conversation in shuffled_tests: if run_only and conversation_name not in run_only: continue if conversation_name in run_exclude: continue print("{0} ...".format(conversation_name)) runner = Runner(conversation) 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(conversation_name) print("Test for the OpenSSL Death Alert (CVE-2016-8610) vulnerability") print("Checks if the server will accept arbitrary number of warning level") print("alerts (specified with the -n option)") 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(): 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 = {} # The payload has to be long enough to trigger heap overflow # Create max. length application data: # 2**14 (max. record size) - 28 ("GET / HTTP/1.0\r\nX-test: " + ending) data_length = 2**14 - 28 # 16 bytes: POLY1305 tag 128 bit # Tampering one bit suffices to damage the mac fuzzes = [(x, 2**y) for x in range(-16, 0) for y in range(8)] for pos, val in fuzzes: conversation = Connect(host, port) 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\r\n" + b'X-test: ' + data_length * b'A' + b'\r\n\r\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_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( ApplicationDataGenerator(b"GET / HTTP/1.0\r\n" + b'X-test: ' + data_length * b'A' + b'\r\n\r\n')) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) # allow for multiple application data records in response node = node.add_child(ExpectApplicationData()) loop = node node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) loop.next_sibling = node 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: 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 = 15 run_exclude = set() expected_failures = {} last_exp_tmp = None private_key = None cert = None exp_illeg_param = False 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, (HashAlgorithm.sha512, SignatureAlgorithm.rsa), (HashAlgorithm.sha384, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa), (HashAlgorithm.sha1, SignatureAlgorithm.rsa) ] argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:k:c:s:", ["help", "illegpar"]) 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, implementations=["python"]) 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 == '-s': sigalgs = sig_algs_to_ids(arg) elif 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 == '--illegpar': exp_illeg_param = 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 if not private_key: raise ValueError("Specify private key file using -k") if not cert: raise ValueError("Specify certificate file using -c") conversations = {} conversations_long = {} conversation = Connect(host, port) node = conversation sigs = [ 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, (HashAlgorithm.sha512, SignatureAlgorithm.rsa), (HashAlgorithm.sha384, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa), (HashAlgorithm.sha1, SignatureAlgorithm.rsa) ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) 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 ] node = node.add_child(ExpectServerKeyExchange(valid_sig_algs=algs)) 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(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(ExpectClose()) conversations["sanity"] = conversation # check if RSA-PSS can be the only one conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) 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(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(ExpectClose()) conversations["RSA-PSS only"] = conversation # check if algs in CertificateRequest are expected conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest(sig_algs=sigalgs)) 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(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(ExpectClose()) conversations["check CertificateRequest sigalgs"] = conversation if cert.certAlg == "rsa": schemes = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_rsae_sha384, SignatureScheme.rsa_pss_rsae_sha512 ] invalid_schemes = [ SignatureScheme.rsa_pss_pss_sha256, SignatureScheme.rsa_pss_pss_sha384, SignatureScheme.rsa_pss_pss_sha512 ] else: schemes = [ SignatureScheme.rsa_pss_pss_sha256, SignatureScheme.rsa_pss_pss_sha384, SignatureScheme.rsa_pss_pss_sha512 ] invalid_schemes = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_rsae_sha384, SignatureScheme.rsa_pss_rsae_sha512 ] for scheme in invalid_schemes: conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(TCPBufferingEnable()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child( CertificateVerifyGenerator(private_key, msg_alg=scheme)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) if exp_illeg_param: node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) else: node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decrypt_error)) node = node.add_child(ExpectClose()) conversations["{0} in CertificateVerify with {1} key".format( SignatureScheme.toRepr(scheme), cert.certAlg)] = conversation # check if CertificateVerify can be signed with any algorithm for scheme in schemes: conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) 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=scheme)) 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() node = node.add_child(ExpectClose()) conversations["{0} in CertificateVerify with {1} key".format( SignatureScheme.toRepr(scheme), cert.certAlg)] = conversation # check if CertificateVerify with wrong salt size is rejected for scheme in schemes: conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(TCPBufferingEnable()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child( CertificateVerifyGenerator(private_key, msg_alg=scheme, rsa_pss_salt_len=20)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decrypt_error)) node = node.add_child(ExpectClose()) conversations[ "{0} in CertificateVerify with incorrect salt len".format( SignatureScheme.toRepr(scheme))] = conversation # check if CertificateVerify with wrong salt size is rejected for pos in range(numBytes(private_key.n)): for xor in [0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80]: conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(TCPBufferingEnable()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) if cert.certAlg == "rsa": scheme = SignatureScheme.rsa_pss_rsae_sha256 else: scheme = SignatureScheme.rsa_pss_pss_sha256 node = node.add_child( CertificateVerifyGenerator(private_key, msg_alg=scheme, padding_xors={pos: xor})) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decrypt_error)) node = node.add_child(ExpectClose()) conversations_long[ "malformed {0} in CertificateVerify - xor {1} at {2}".format( cert.certAlg, hex(xor), pos)] = conversation if cert.certAlg == "rsa-pss": conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(TCPBufferingEnable()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child( CertificateVerifyGenerator( private_key, msg_alg=SignatureScheme.rsa_pkcs1_sha256, sig_alg=SignatureScheme.rsa_pkcs1_sha256)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) if exp_illeg_param: node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) else: node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decrypt_error)) node = node.add_child(ExpectClose()) conversations["rsa_pkcs1_sha256 signature in CertificateVerify " "with rsa-pss key"] = conversation conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(TCPBufferingEnable()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) if cert.certAlg == "rsa": sig_alg = SignatureScheme.rsa_pss_rsae_sha256 else: sig_alg = SignatureScheme.rsa_pss_pss_sha256 node = node.add_child( CertificateVerifyGenerator(private_key, msg_alg=SignatureScheme.rsa_pkcs1_sha256, sig_alg=sig_alg)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) if exp_illeg_param and cert.certAlg != "rsa": node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.illegal_parameter)) else: # with rsaEncryption key in certificate, there is nothing the TLS # layer can inspect to decide if the signature is valid before actually # verifying it # for rsassa-pss, rsa_pkcs1 signature is illegal node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decrypt_error)) node = node.add_child(ExpectClose()) conversations[ "{0} signature in CertificateVerify with rsa_pkcs1_sha256 id".format( SignatureScheme.toRepr(sig_alg))] = conversation conversation = Connect(host, port) node = conversation sigs = [ 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 ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs), 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 ] 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(ExpectServerKeyExchange()) node = node.add_child(ExpectCertificateRequest()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(TCPBufferingEnable()) node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) if cert.certAlg == "rsa": scheme = SignatureScheme.rsa_pss_rsae_sha256 else: scheme = SignatureScheme.rsa_pss_pss_sha256 sig = bytearray(b'\xfa\xbc\x0f\x4c') node = node.add_child( CertificateVerifyGenerator(private_key, msg_alg=scheme, signature=sig)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decrypt_error)) node = node.add_child(ExpectClose()) conversations["short sig with {0} id".format( SignatureScheme.toRepr(scheme))] = 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'])] if run_only: if num_limit > len(run_only): num_limit = len(run_only) long_tests = [(k, v) for k, v in conversations_long.items() if k in run_only] short_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k in run_only] else: long_tests = [(k, v) for k, v in conversations_long.items() if k not in run_exclude] short_tests = [(k, v) for k, v in conversations.items() if (k != 'sanity') and k not in run_exclude] sampled_tests = sample(long_tests, min(num_limit, len(long_tests))) ordered_tests = chain(sanity_tests, short_tests, sampled_tests, sanity_tests) for c_name, c_test in ordered_tests: 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 handling of rsa-pss signatures") print("Test should be run twice, once with certificate with") print("rsaEncryption key and once with certificate with rsassa-pss key.") print("Implementations that inspect certificate type and check signature") print("scheme in CertificateVerify before verifying signature need to use") print("--illegpar option") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format( len(sampled_tests) + len(short_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 nonces used by server are monotonically increasing""" conversations = {} nonces = [] conversation = Connect("localhost", 4433) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256] 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(CollectNonces(nonces)) 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["aes-128-gcm cipher"] = conversation nonces256 = [] 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(CollectNonces(nonces256)) 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["aes-256-gcm cipher"] = 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("aes-128-gcm Nonce monotonicity...") if len(nonces) < 2: print("Not enough nonces collected, FAIL") bad += 1 else: if bytesToNumber(nonces[0]) == bytesToNumber(nonces[1]): print("reused nonce! Security vulnerability!") bad += 1 elif bytesToNumber(nonces[0]) + 1 != bytesToNumber(nonces[1]): print("nonce not monotonically increasing, FAIL") bad += 1 else: print("OK\n") good += 1 print("aes-256-gcm Nonce monotonicity...") if len(nonces256) < 2: print("Not enough nonces collected, FAIL") bad += 1 else: if bytesToNumber(nonces256[0]) == bytesToNumber(nonces256[1]): print("reused nonce! Security vulnerability!") bad += 1 elif bytesToNumber(nonces256[0]) + 1 != bytesToNumber(nonces256[1]): print("nonce not monotonically increasing, FAIL") bad += 1 else: print("OK\n") good += 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 = 500 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, version=(3, 3))) 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"] = conversation conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} node = node.add_child( ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext)) 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 w/ext"] = conversation # test different message types for client hello for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] hello_gen = ClientHelloGenerator(ciphers, version=(3, 3)) node = node.add_child(fuzz_message(hello_gen, xors={0: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.unexpected_message)) node = node.add_child(ExpectClose()) conversations["Client Hello type fuzz to {0}".format( 1 ^ i)] = conversation # test invalid sizes for session ID length for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] hello_gen = ClientHelloGenerator(ciphers, version=(3, 3)) node = node.add_child(fuzz_message(hello_gen, substitutions={38: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["session ID len fuzz to {0}".format(i)] = conversation for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} hello_gen = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(fuzz_message(hello_gen, substitutions={38: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["session ID len fuzz to {0} w/ext".format( i)] = conversation # test invalid sizes for cipher suites length for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] hello_gen = ClientHelloGenerator(ciphers, version=(3, 3)) node = node.add_child(fuzz_message(hello_gen, xors={40: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["cipher suites len fuzz to {0}".format( 4 ^ i)] = conversation for i in (1, 2, 4, 8, 16, 128, 254, 255): for j in range(0, 0x100): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] hello_gen = ClientHelloGenerator(ciphers, version=(3, 3)) node = node.add_child( fuzz_message(hello_gen, substitutions={ 39: i, 40: j })) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["cipher suites len fuzz to {0}".format( (i << 8) + j)] = conversation for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} hello_gen = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(fuzz_message(hello_gen, xors={40: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["cipher suites len fuzz to {0} w/ext".format( 4 ^ i)] = conversation for i in (1, 2, 4, 8, 16, 128, 254, 255): for j in range(0, 0x100): conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} hello_gen = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child( fuzz_message(hello_gen, substitutions={ 39: i, 40: j })) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["cipher suites len fuzz to {0} w/ext".format( (i << 8) + j)] = conversation # test invalid sizes for compression methods for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] hello_gen = ClientHelloGenerator(ciphers, version=(3, 3)) node = node.add_child(fuzz_message(hello_gen, xors={45: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["compression methods len fuzz to {0}".format( 1 ^ i)] = conversation for i in range(1, 0x100): if 1 ^ i == 8: # this length creates a valid extension-less hello continue conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} hello_gen = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(fuzz_message(hello_gen, xors={43: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["compression methods len fuzz to {0} w/ext".format( 1 ^ i)] = conversation # test invalid sizes for extensions for i in range(1, 0x100): conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} hello_gen = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child(fuzz_message(hello_gen, xors={46: i})) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["extensions len fuzz to {0}".format(5 ^ i)] = conversation for i in (1, 2, 4, 8, 16, 254, 255): for j in range(0, 0x100): conversation = Connect(host, port) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] ext = {ExtensionType.renegotiation_info: None} hello_gen = ClientHelloGenerator(ciphers, version=(3, 3), extensions=ext) node = node.add_child( fuzz_message(hello_gen, substitutions={ 45: i, 46: j })) node = node.add_child( ExpectAlert(level=AlertLevel.fatal, description=AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["extensions len fuzz to {0}".format( (i << 8) + j)] = conversation # run the conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] # 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: 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("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 malformed messages related to client certs are rejected.""" conversations = {} host = "localhost" port = 4433 run_exclude = set() private_key = None cert = None argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e: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 == '-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 not private_key: raise ValueError("Specify private key file using -k") if not cert: raise ValueError("Specify certificate file using -c") if args: run_only = set(args) else: run_only = None # sanity check for Client Certificates 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', '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 # sanity check for no client certificate 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', '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(None)) 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 - no client cert"] = conversation for i in range(1, 0x100): 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', '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(TCPBufferingEnable()) node = node.add_child( fuzz_message(CertificateGenerator(X509CertChain([cert])), xors={7: i})) 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(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["fuzz certificates length with {0}".format( i)] = conversation for i in range(1, 0x100): 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', '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(TCPBufferingEnable()) node = node.add_child( fuzz_message(CertificateGenerator(X509CertChain([cert])), xors={9: i})) 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(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["fuzz first certificate length with {0}".format( i)] = conversation # fuzz empty certificates message for i in range(1, 0x100): 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', '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(TCPBufferingEnable()) node = node.add_child( fuzz_message(CertificateGenerator(None), xors={-1: i})) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["fuzz empty certificates length - {0}".format( i)] = conversation # sanity check for no client certificate 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', '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(TCPBufferingEnable()) # technically, it's an invalid encoding as the items are defined as # <1..2^24-1>, but some implementations, like OpenSSL, accept it; # don't be too precise for now msg = CertificateGenerator() msg = pad_handshake(msg, 3) msg = fuzz_message(msg, substitutions={-4: 3}) node = node.add_child(msg) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectChangeCipherSpec()) # if the implementation is proper, it will reject the message node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error) node.next_sibling.add_child(ExpectClose()) 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 - empty client cert"] = conversation # fuzz empty certificate message for i, j, k in ((i, j, k) for i in range(8) for j in range(8) for k in range(6)): if i == 3 and j == 0 or k == 0 and i == 0: continue 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', '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(TCPBufferingEnable()) msg = CertificateGenerator() msg = pad_handshake(msg, k) subs = {6: i} if k >= 3: subs[9] = j msg = fuzz_message(msg, substitutions=subs) node = node.add_child(msg) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations[ "fuzz empty certificate - overall {2}, certs {0}, cert {1}".format( i, j, k + 3)] = 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("Malformed Certificate 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(): """Test version numbers outside used range""" 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, version=(3, 0)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None}, version=(254, 254))) node = node.add_child(ExpectServerHello(version=(3, 3), 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["very high version (254, 254)"] = conversation conversation = Connect(host, port, version=(3, 0)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None}, version=(0, 0))) node = node.add_child(ExpectAlert(description=AlertDescription.protocol_version)) node = node.add_child(ExpectClose()) conversations["very low version (0, 0)"] = conversation conversation = Connect(host, port, version=(3, 0)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None}, version=(3, 3))) node = node.add_child(ExpectServerHello(version=(3, 3), 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["low record version (3, 0), TLS1.2 (sanity check)"] = conversation conversation = Connect(host, port, version=(3, 254)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None}, version=(3, 3))) node = node.add_child(ExpectServerHello(version=(3, 3), 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["high record version (3, 254), TLS1.2"] = conversation conversation = Connect(host, port, version=(3, 254)) node = conversation ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions={ExtensionType.renegotiation_info:None}, version=(254, 254))) node = node.add_child(ExpectServerHello(version=(3, 3), 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["high record version (3, 254), very high protocol version (254, 254)"] = 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: 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 run_exclude = set() ssl3 = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:", ["help", "ssl3"]) 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 == '--ssl3': ssl3 = True else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port, version=(3, 0)) 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 for c_id, name in [(0x0003, "TLS_RSA_EXPORT_WITH_RC4_40_MD5"), (0x0006, "TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5"), (0x0008, "TLS_RSA_EXPORT_WITH_DES40_CBC_SHA"), (0x000B, "TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA"), (0x000E, "TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA"), (0x0011, "TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"), (0x0014, "TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA"), (0x0017, "TLS_DH_anon_EXPORT_WITH_RC4_40_MD5"), (0x0019, "TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA"), (0x0026, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_SHA"), (0x0027, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_SHA"), (0x0028, "TLS_KRB5_EXPORT_WITH_RC4_40_SHA"), (0x0029, "TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5"), (0x002A, "TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5"), (0x002B, "TLS_KRB5_EXPORT_WITH_RC4_40_MD5"), (0x0062, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA"), (0x0063, "TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA"), (0x0064, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA"), (0x0065, "TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA")]: for prot, prot_name in [((3, 3), "TLSv1.2"), ((3, 2), "TLSv1.1"), ((3, 1), "TLSv1.0"), ((3, 0), "SSLv3")]: conversation = Connect(host, port, version=(3, 0)) node = conversation ciphers = [ c_id, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, version=prot)) if prot == (3, 0) and not ssl3: node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.protocol_version)) node = node.add_child(ExpectClose()) else: node = node.add_child( ExpectServerHello( cipher=CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA)) 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)) # allow for 1/n-1 record splitting node = node.add_child(ExpectApplicationData()) record_split = node node.next_sibling = ExpectAlert(AlertLevel.warning, AlertDescription.close_notify) node.next_sibling.next_sibling = ExpectClose() node = record_split.add_child(record_split.next_sibling) node.add_child(ExpectClose()) conversations["{0} with AES_128 in {1}".format(name, prot_name)] \ = conversation # alone conversation = Connect(host, port, version=(3, 0)) node = conversation ciphers = [c_id, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV] node = node.add_child(ClientHelloGenerator(ciphers)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectClose()) conversations["{0} in {1}".format(name, prot_name)] = 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 if export grade ciphers are rejected by server. Version 2\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(): """Test if server supports the DHE_RSA key exchange""" 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 = {} # sanity check conversation = Connect(host, port) 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(version=(3, 3), 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"] = conversation # sanity check - TLS 1.1 enabled conversation = Connect(host, port) 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(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 - TLS 1.1 enabled"] = conversation # check TLSv1.2 ciphers without TLSv1.2 client hello for cipher in CipherSuite.tls12Suites: conversation = Connect(host, port) node = conversation ciphers = [cipher] node = node.add_child(ClientHelloGenerator(ciphers, version=(3, 2), extensions={ExtensionType. renegotiation_info:None})) node = node.add_child(ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node.add_child(ExpectClose()) conversations[CipherSuite.ietfNames[cipher] + " in TLSv1.1"] =\ 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("Script to verify that server does not negotiate TLS1.2 ciphers") print("in TLS1.1 or earlier protocol") 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 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()) 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 (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 or xpass: sys.exit(1)
def main(): """check if obsolete signature algorithm is rejected by server""" conversations = {} hostname = "localhost" port = 4433 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': 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 == '--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 = [] print("Certificate Verify test version 4") sanity_tests = [('sanity', conversations['sanity'])] regular_tests = [(k, v) for k, v in conversations.items() if k != 'sanity'] sampled_tests = sample(regular_tests, 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("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 obsolete signature algorithm is rejected by server""" conversations = {} hostname = "localhost" port = 4433 run_exclude = set() private_key = None cert = None argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:e: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': 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 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 failed = [] print("Certificate Verify test version 4") 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 #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\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 server correctly handles some obviously wrong messages""" 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] 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"] = conversation # set the whole value post encryption to zero's for size in (128, 256, 384, 512): conversation = Connect(host, port) 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(TCPBufferingEnable()) node = node.add_child( ClientKeyExchangeGenerator(encrypted_premaster=bytearray(size))) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node.add_child(ExpectClose()) conversations["encrypted premaster set to all zero ({0})".format(size)] =\ conversation # set the encrypted premaster to the the value of server modulus conversation = Connect(host, port) 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(TCPBufferingEnable()) node = node.add_child( ClientKeyExchangeGenerator(modulus_as_encrypted_premaster=True)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac)) node.add_child(ExpectClose()) conversations["modulus as encrypted premaster"] = 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 server can handle handshake protocol messages fragmented over # multiple records # 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: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 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 ] ext = {21: TLSExtension().create(21, bytearray(10))} node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) 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"] = conversation # 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), ("medium hello, pow2 fragmentation", 1024, 127), ("medium hello, pow2 fragmentation", 1024, 128), ("medium hello, pow2 fragmentation", 1024, 128), ("medium hello, pow2 fragmentation", 1024, 255), ("medium hello, pow2 fragmentation", 1024, 256), ("medium hello, pow2 fragmentation", 1024, 257), ("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) ]: conversation = Connect(host, port) node = conversation node = node.add_child(SetMaxRecordSize(record_len)) ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {21: TLSExtension().create(21, bytearray(ext_len))} node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) 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()) # XXX 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 = TLSExtension().create(21, bytearray(2**14 - 52)) conversation = Connect(host, port) 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 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(): 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 # # Test sending invalid (too short or too long) Client Key Exchange messages # conver = Connect(host, port) 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(pad_handshake(ClientKeyExchangeGenerator(), 1)) #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["padded Client Key Exchange"] = conver conver = Connect(host, port) 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(truncate_handshake(ClientKeyExchangeGenerator(), 1)) #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["truncated Client Key Exchange"] = conver # 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 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 # 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"] = conversation # CVE-2016-2107 reproducer # to reproduce the vulnerability we need to send a packet that decrypts # to 32 ASCII "A" bytes conversation = Connect(host, port) 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=dict((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 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("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)