def test___repr__(self): ext = TLSExtension() ext = ext.create(0, bytearray(b'\x00\x00')) self.assertEqual("TLSExtension(extType=0, "\ "extData=bytearray(b'\\x00\\x00'), serverType=False)", repr(ext))
def test___repr__(self): ext = TLSExtension() ext = ext.create(0, bytearray(b'\x00\x00')) self.assertEqual("TLSExtension(ext_type=0, "\ "ext_data=bytearray(b'\\x00\\x00'), server_type=False)", repr(ext))
def test_write_with_data(self): tls_extension = TLSExtension().create(44, bytearray(b'garbage')) self.assertEqual( bytearray(b'\x00\x2c' + # type of extension - 44 b'\x00\x07' + # length of extension - 7 bytes # utf-8 encoding of "garbage" b'\x67\x61\x72\x62\x61\x67\x65'), tls_extension.write())
def test_write_with_data(self): tls_extension = TLSExtension().create(44, bytearray(b'garbage')) self.assertEqual(bytearray( b'\x00\x2c' + # type of extension - 44 b'\x00\x07' + # length of extension - 7 bytes # utf-8 encoding of "garbage" b'\x67\x61\x72\x62\x61\x67\x65' ), tls_extension.write())
def test_getExtension_with_present_id(self): client_hello = ClientHello().create( (3, 3), bytearray(1), bytearray(0), [], extensions=[TLSExtension().create(0, bytearray(0))]) ext = client_hello.getExtension(0) self.assertEqual(ext, TLSExtension().create(0, bytearray(0)))
def test_parse_of_server_hello_extension(self): ext = TLSExtension(server=True) p = Parser( bytearray(b'\x00\x09' + # extension type - cert_type (9) b'\x00\x01' + # extension length - 1 byte b'\x01' # certificate type - OpenGPG (1) )) ext = ext.parse(p) self.assertEqual(1, ext.cert_type)
def test_parse_of_server_hello_extension(self): ext = TLSExtension(server=True) p = Parser(bytearray( b'\x00\x09' + # extension type - cert_type (9) b'\x00\x01' + # extension length - 1 byte b'\x01' # certificate type - OpenGPG (1) )) ext = ext.parse(p) self.assertEqual(1, ext.cert_type)
def test_parse_with_client_cert_type_extension(self): ext = TLSExtension() p = Parser( bytearray(b'\x00\x09' + # ext type b'\x00\x02' + # ext length b'\x01' + # length of array b'\x01')) # type - opengpg (1) ext = ext.parse(p) self.assertIsInstance(ext, ClientCertTypeExtension) self.assertEqual([1], ext.certTypes)
def test_parse_with_client_cert_type_extension(self): ext = TLSExtension() p = Parser(bytearray( b'\x00\x09' + # ext type b'\x00\x02' + # ext length b'\x01' + # length of array b'\x01')) # type - opengpg (1) ext = ext.parse(p) self.assertIsInstance(ext, ClientCertTypeExtension) self.assertEqual([1], ext.certTypes)
def __init__(self): """Set the configuration to Firefox 42.""" super(Firefox_42, self).__init__() self._name = "Firefox 42" self.version = (3, 3) self.record_version = (3, 1) self.ciphers = [ CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA, CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA ] ext = self.extensions = [] ext.append(SNIExtension()) ext.append( TLSExtension(extType=ExtensionType.renegotiation_info).create( bytearray(1))) ext.append(SupportedGroupsExtension().create( [GroupName.secp256r1, GroupName.secp384r1, GroupName.secp521r1])) ext.append(ECPointFormatsExtension().create( [ECPointFormat.uncompressed])) ext.append(TLSExtension(extType=ExtensionType.session_ticket)) ext.append(NPNExtension()) ext.append( TLSExtension(extType=ExtensionType.alpn).create( bytearray(b'\x00\x15' + b'\x02' + b'h2' + b'\x08' + b'spdy/3.1' + b'\x08' + b'http/1.1'))) ext.append( TLSExtension(extType=ExtensionType.status_request).create( bytearray(b'\x01' + b'\x00\x00' + b'\x00\x00'))) sig_algs = [] for alg in ['sha256', 'sha384', 'sha512', 'sha1']: sig_algs.append((getattr(HashAlgorithm, alg), SignatureAlgorithm.rsa)) for alg in ['sha256', 'sha384', 'sha512', 'sha1']: sig_algs.append((getattr(HashAlgorithm, alg), SignatureAlgorithm.ecdsa)) for alg in ['sha256', 'sha1']: sig_algs.append((getattr(HashAlgorithm, alg), SignatureAlgorithm.dsa)) ext.append(SignatureAlgorithmsExtension().create(sig_algs))
def test_new_style_create_with_keyword(self): tls_extension = TLSExtension(extType=1).create(data=\ bytearray(b'\x01\x00')) self.assertIsNotNone(tls_extension) self.assertEqual(1, tls_extension.extType) self.assertEqual(bytearray(b'\x01\x00'), tls_extension.extData)
def test_parse_with_TACK_extension(self): p = Parser( bytearray( # we don't include the type of message as it is handled by the # hello protocol parser #b'x01' + # type of message - client_hello b'\x00' * 2 + b'\x2c' + # length - 44 bytes b'\x01\x01' + # protocol version - arbitrary (invalid) b'\x00' * 32 + # client random b'\x00' + # session ID length b'\x00' * 2 + # cipher suites length b'\x00' + # compression methods length b'\x00\x04' + # extensions length - 4 bytes b'\xf3\x00' + # extension type - TACK (62208) b'\x00\x00' # extension length - 0 bytes )) client_hello = ClientHello() client_hello = client_hello.parse(p) self.assertEqual((1, 1), client_hello.client_version) self.assertEqual(bytearray(32), client_hello.random) self.assertEqual(bytearray(0), client_hello.session_id) self.assertEqual([], client_hello.cipher_suites) self.assertEqual([], client_hello.compression_methods) self.assertEqual(True, client_hello.tack) tack = TLSExtension().create(62208, bytearray(0)) self.assertEqual([tack], client_hello.extensions)
def test_parse_with_length_long_by_one(self): p = Parser( bytearray(b'\x00\x42' + # type of extension b'\x00\x03' + # length of rest of data b'\xff\xfa' # value of extension )) with self.assertRaises(SyntaxError) as context: TLSExtension().parse(p)
def test_equality_with_nearly_good_object(self): class TestClass(object): def __init__(self): self.extType = 0 a = TLSExtension().create(0, bytearray(b'\x00\x00')) b = TestClass() self.assertFalse(a == b)
def test_parse(self): p = Parser( bytearray(b'\x00\x42' + # type of extension b'\x00\x01' + # length of rest of data b'\xff' # value of extension )) tls_extension = TLSExtension().parse(p) self.assertEqual(66, tls_extension.extType) self.assertEqual(bytearray(b'\xff'), tls_extension.extData)
def test_parse_with_SNI_server_side(self): p = Parser( bytearray(b'\x00\x00' + # type of extension - SNI b'\x00\x00' # overall length - 0 bytes )) ext = TLSExtension(server=True).parse(p) self.assertIsInstance(ext, SNIExtension) self.assertIsNone(ext.serverNames)
def test___str___with_extensions(self): client_hello = ClientHello().create((3,0), bytearray(4), bytearray(0),\ [], extensions=[TLSExtension().create(0, bytearray(b'\x00'))]) self.assertEqual("client_hello,version(3.0),random(...),"\ "session ID(bytearray(b'')),cipher suites([]),"\ "compression methods([0]),extensions(["\ "TLSExtension(extType=0, extData=bytearray(b'\\x00'), "\ "serverType=False)])", str(client_hello))
def test_getExtension(self): client_hello = ClientHello().create( (3, 3), bytearray(1), bytearray(0), [], extensions=[TLSExtension().create(0, bytearray(0))]) ext = client_hello.getExtension(1) self.assertIsNone(ext)
def test___repr__(self): client_hello = ClientHello().create((3,3), bytearray(1), bytearray(0),\ [], extensions=[TLSExtension().create(0, bytearray(0))]) self.assertEqual("ClientHello(ssl2=False, client_version=(3.3), "\ "random=bytearray(b'\\x00'), session_id=bytearray(b''), "\ "cipher_suites=[], compression_methods=[0], "\ "extensions=[TLSExtension(extType=0, "\ "extData=bytearray(b''), serverType=False)])", repr(client_hello))
def test_parse_with_NPN_ext(self): p = Parser( bytearray(b'\x33\x74' + # type of extension - NPN b'\x00\x09' + # overall length b'\x08' + # first name length b'http/1.1')) ext = TLSExtension().parse(p) self.assertIsInstance(ext, NPNExtension) self.assertEqual(ext.protocols, [b'http/1.1'])
def test_getExtension_with_duplicated_extensions(self): client_hello = ClientHello().create( (3, 3), bytearray(1), bytearray(0), [], extensions=[ TLSExtension().create(0, bytearray(0)), SNIExtension().create(b'localhost') ]) with self.assertRaises(TLSInternalError): client_hello.getExtension(0)
def test_parse_with_SRP_ext(self): p = Parser( bytearray(b'\x00\x0c' + # ext type - 12 b'\x00\x09' + # overall length b'\x08' + # name length b'username' # name )) ext = TLSExtension().parse(p) self.assertIsInstance(ext, SRPExtension) self.assertEqual(ext.identity, b'username')
def test_parse_with_ec_point_formats(self): p = Parser( bytearray(b'\x00\x0b' + # type of extension b'\x00\x02' + # overall length b'\x01' + # length of array b'\x00' # type - uncompressed )) ext = TLSExtension().parse(p) self.assertIsInstance(ext, ECPointFormatsExtension) self.assertEqual(ext.formats, [ECPointFormat.uncompressed])
def test_parse_with_sni_ext(self): p = Parser( bytearray(b'\x00\x00' + # type of extension - SNI (0) b'\x00\x10' + # length of extension - 16 bytes b'\x00\x0e' + # length of array b'\x00' + # type of entry - host_name (0) b'\x00\x0b' + # length of name - 11 bytes # UTF-8 encoding of example.com b'\x65\x78\x61\x6d\x70\x6c\x65\x2e\x63\x6f\x6d')) tls_extension = TLSExtension().parse(p) self.assertEqual(bytearray(b'example.com'), tls_extension.hostNames[0])
def test_parse_with_renego_info_server_side(self): p = Parser( bytearray(b'\xff\x01' + # type of extension - renegotiation_info b'\x00\x01' + # overall length b'\x00' # extension length )) ext = TLSExtension(server=True).parse(p) # XXX not supported self.assertIsInstance(ext, TLSExtension) self.assertEqual(ext.extData, bytearray(b'\x00')) self.assertEqual(ext.extType, 0xff01)
def _generate_extensions(self, state): """Convert extension generators to extension objects""" extensions = [] for ext_id in self.extensions: if self.extensions[ext_id] is not None: extensions.append(self.extensions[ext_id](state)) continue if ext_id == ExtensionType.renegotiation_info: ext = RenegotiationInfoExtension().create( state.client_verify_data) extensions.append(ext) else: extensions.append(TLSExtension().create(ext_id, bytearray(0))) return extensions
def test_parse_with_elliptic_curves(self): p = Parser( bytearray(b'\x00\x0a' + # type of extension b'\x00\x08' + # overall length b'\x00\x06' + # length of array b'\x00\x17' + # secp256r1 b'\x00\x18' + # secp384r1 b'\x00\x19' # secp521r1 )) ext = TLSExtension().parse(p) self.assertIsInstance(ext, SupportedGroupsExtension) self.assertEqual( ext.groups, [GroupName.secp256r1, GroupName.secp384r1, GroupName.secp521r1])
def test_process_with_extended_master_secret(self): exp = ExpectServerHello( extensions={ExtensionType.extended_master_secret: None}) state = ConnectionState() state.msg_sock = mock.MagicMock() self.assertFalse(state.extended_master_secret) ext = TLSExtension(extType=ExtensionType.extended_master_secret) msg = ServerHello().create(version=(3, 3), random=bytearray(32), session_id=bytearray(0), cipher_suite=4, extensions=[ext]) self.assertTrue(exp.is_match(msg)) exp.process(state, msg) self.assertTrue(state.extended_master_secret)
def _generate_extensions(self, state): """Convert extension generators to extension objects""" extensions = [] for ext_id in self.extensions: if self.extensions[ext_id] is not None: if callable(self.extensions[ext_id]): extensions.append(self.extensions[ext_id](state)) elif isinstance(self.extensions[ext_id], TLSExtension): extensions.append(self.extensions[ext_id]) else: raise ValueError("Bad extension, id: {0}".format(ext_id)) continue if ext_id == ExtensionType.renegotiation_info: ext = RenegotiationInfoExtension().create( state.client_verify_data) extensions.append(ext) else: extensions.append(TLSExtension().create(ext_id, bytearray(0))) return extensions
def test_parse_with_signature_algorithms(self): p = Parser( bytearray(b'\x00\x0d' + # type of extension b'\x00\x1c' + # overall length b'\x00\x1a' + # length of array b'\x04\x01' + # SHA256+RSA b'\x04\x02' + # SHA256+DSA b'\x04\x03' + # SHA256+ECDSA b'\x05\x01' + # SHA384+RSA b'\x05\x03' + # SHA384+ECDSA b'\x06\x01' + # SHA512+RSA b'\x06\x03' + # SHA512+ECDSA b'\x03\x01' + # SHA224+RSA b'\x03\x02' + # SHA224+DSA b'\x03\x03' + # SHA224+ECDSA b'\x02\x01' + # SHA1+RSA b'\x02\x02' + # SHA1+DSA b'\x02\x03' # SHA1+ECDSA )) ext = TLSExtension().parse(p) self.assertIsInstance(ext, SignatureAlgorithmsExtension) self.assertEqual(ext.sigalgs, [(HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.dsa), (HashAlgorithm.sha256, SignatureAlgorithm.ecdsa), (HashAlgorithm.sha384, SignatureAlgorithm.rsa), (HashAlgorithm.sha384, SignatureAlgorithm.ecdsa), (HashAlgorithm.sha512, SignatureAlgorithm.rsa), (HashAlgorithm.sha512, SignatureAlgorithm.ecdsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.dsa), (HashAlgorithm.sha224, SignatureAlgorithm.ecdsa), (HashAlgorithm.sha1, SignatureAlgorithm.rsa), (HashAlgorithm.sha1, SignatureAlgorithm.dsa), (HashAlgorithm.sha1, SignatureAlgorithm.ecdsa)])
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(): # # 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() expected_failures = {} last_exp_tmp = None dhe = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:x:X:n:d", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-d': dhe = True elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation if dhe: ext = {} groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create( [SignatureScheme.rsa_pkcs1_sha256, SignatureScheme.rsa_pss_rsae_sha256]) ext[ExtensionType.signature_algorithms_cert] = \ SignatureAlgorithmsCertExtension().create(RSA_SIG_ALL) ciphers = [ CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] else: ext = None ciphers = [ CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectCertificate()) if dhe: node = node.add_child(ExpectServerKeyExchange()) node = node.add_child(ExpectServerHelloDone()) node = node.add_child(ClientKeyExchangeGenerator()) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) node = node.add_child(ExpectApplicationData()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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()) 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["only http/1.1"] = conversation conversation = Connect(host, port) node = conversation ext = {ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.')])} 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)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.no_application_protocol)) node.add_child(ExpectClose()) conversations["only http/1."] = conversation conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.X')]) } 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)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.no_application_protocol)) node.add_child(ExpectClose()) conversations["only http/1.X"] = conversation conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.'), bytearray(b'http/1.1')]) } 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)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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()) 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["http/1. and http/1.1"] = conversation conversation = Connect(host, port) node = conversation ext = {ExtensionType.alpn: ALPNExtension().create([bytearray(b'')])} 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)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.add_child(ExpectClose()) conversations["empty element"] = conversation conversation = Connect(host, port) node = conversation ext = {ExtensionType.alpn: ALPNExtension().create([])} 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)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.add_child(ExpectClose()) conversations["empty list"] = conversation conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: TLSExtension(extType=ExtensionType.alpn).create(bytearray()) } 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)) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node.add_child(ExpectClose()) conversations["empty extension"] = conversation # underflow length of "protocol_name_list" test conversation = Connect(host, port) node = conversation # the ALPN extension needs to be the last one for fuzz_message to work # correctly ext = OrderedDict() 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 ] ext[ExtensionType.alpn] = ALPNExtension().create( [bytearray(b'http/1.1'), bytearray(b'http/2')]) msg = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) # -17 is position of second byte in 2 byte long length of "protocol_name_list" # setting it to value of 9 (bytes) will hide the second item in the "protocol_name_list" node = node.add_child(fuzz_message(msg, substitutions={-17: 9})) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["underflow length of protocol_name_list"] = conversation # overflow length of "protocol_name_list" test conversation = Connect(host, port) node = conversation # the ALPN extension needs to be the last one for fuzz_message to work # correctly ext = OrderedDict() 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 ] ext[ExtensionType.alpn] = ALPNExtension().create( [bytearray(b'http/1.1'), bytearray(b'http/2')]) msg = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) # -17 is position of second byte in 2 byte long length of "protocol_name_list" # setting it to value of 18 (bytes) will raise the length value for 2 more bytes node = node.add_child(fuzz_message(msg, substitutions={-17: 18})) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["overflow length of protocol_name_list"] = conversation # overflow length of last item in "protocol_name_list" test conversation = Connect(host, port) node = conversation # the ALPN extension needs to be the last one for fuzz_message to work # correctly ext = OrderedDict() 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 ] ext[ExtensionType.alpn] = ALPNExtension().create( [bytearray(b'http/1.1'), bytearray(b'http/2')]) msg = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) # -7 is position of a length (1 byte long) for the last item in "protocol_name_list" # setting it to value of 8 (bytes) will raise the length value for 2 more bytes node = node.add_child(fuzz_message(msg, substitutions={-7: 8})) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["overflow length of last item"] = conversation # renegotiation with protocol change conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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.alpn: ALPNExtension().create([bytearray(b'http/2')]), ExtensionType.renegotiation_info: None } if dhe: add_dhe_extensions(ext) node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/2')]) } 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()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["renegotiation with protocol change"] = conversation # renegotiation without protocol change conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } if dhe: add_dhe_extensions(ext) node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["renegotiation without protocol change"] = conversation # renegotiation 2nd handshake alpn conversation = Connect(host, port) node = conversation ext = {ExtensionType.renegotiation_info: None} 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 ] 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.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } if dhe: add_dhe_extensions(ext) node = node.add_child( ClientHelloGenerator(ciphers, session_id=bytearray(0), extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["renegotiation 2nd handshake alpn"] = conversation # resumption without alpn change conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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()) 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()) ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } if dhe: add_dhe_extensions(ext) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } node = node.add_child(ExpectServerHello(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( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["resumption without alpn change"] = conversation # resumption with alpn change conversation = Connect(host, port) node = conversation ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } 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 ] else: ciphers = [CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA] node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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()) 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()) ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'h2')]), ExtensionType.renegotiation_info: None } if dhe: add_dhe_extensions(ext) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'h2')]) } node = node.add_child(ExpectServerHello(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( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["resumption with alpn change"] = conversation # resumption with alpn conversation = Connect(host, port) node = conversation ext = {ExtensionType.renegotiation_info: None} 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 ] 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()) 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()) ext = { ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]), ExtensionType.renegotiation_info: None } if dhe: add_dhe_extensions(ext) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) ext = { ExtensionType.renegotiation_info: None, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } node = node.add_child(ExpectServerHello(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( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() node = node.add_child(ExpectClose()) conversations["resumption with alpn"] = conversation # 16269 byte long array and 255 byte long items test # Client Hello longer than 2^14 bytes conversation = Connect(host, port) node = conversation proto = bytearray(b"A" * 255) lista = [] lista.append(proto) # 63 items 255 bytes long + 1 item 195 bytes long + 1 item 8 byte long (http/1.1) for p in range(1, 63): lista.append(proto) if dhe: # (in DHE we send more extensions and longer cipher suite list, so the # extension has to be shorter) # 145 + 1 byte to reproduce the issue lista.append(bytearray(b'B' * 146)) else: # 195 + 1 byte to reproduce the issue lista.append(bytearray(b'B' * 196)) lista.append(bytearray(b'http/1.1')) ext = {ExtensionType.alpn: ALPNExtension().create(lista)} if dhe: groups = [GroupName.secp256r1, GroupName.ffdhe2048] ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension().create( [SignatureScheme.rsa_pkcs1_sha256, SignatureScheme.rsa_pss_rsae_sha256]) 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, ExtensionType.alpn: ALPNExtension().create([bytearray(b'http/1.1')]) } 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()) node = node.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["16269 byte long array"] = 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("ALPN extension tests") print("Verify that the ALPN extenion is supported in the server and has") print("correct error handling.") 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 run_exclude = set() argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} conversation = Connect(host, port) node = conversation sigs = [(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) } 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(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() node = node.add_child(ExpectClose()) conversations["sanity"] = conversation # now with RSA-PSS conversation = Connect(host, port) node = conversation sigs = [ SignatureScheme.rsa_pss_sha256, SignatureScheme.rsa_pss_sha384, SignatureScheme.rsa_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) } 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(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() node = node.add_child(ExpectClose()) conversations["with RSA-PSS"] = conversation for sig in [ SignatureScheme.rsa_pss_sha256, SignatureScheme.rsa_pss_sha384, SignatureScheme.rsa_pss_sha512 ]: conversation = Connect(host, port) node = conversation ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([sig]) } 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(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() node = node.add_child(ExpectClose()) conversations["{0} only".format( SignatureScheme.toRepr(sig))] = conversation # MD5 not selected, even if first conversation = Connect(host, port) node = conversation sigs = [(HashAlgorithm.md5, SignatureAlgorithm.rsa), (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) } 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(valid_sig_algs=sigs[1:])) 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() node = node.add_child(ExpectClose()) conversations["MD5 first"] = conversation conversation = Connect(host, port) node = conversation sigs = [(HashAlgorithm.md5, SignatureAlgorithm.rsa), (HashAlgorithm.sha512, SignatureAlgorithm.rsa), (HashAlgorithm.sha384, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs) } 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(valid_sig_algs=sigs[1:])) 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() node = node.add_child(ExpectClose()) conversations["MD5 first, no SHA-1"] = conversation # sha-1 must not be the only option conversation = Connect(host, port) node = conversation sigs = [(HashAlgorithm.sha512, SignatureAlgorithm.rsa), (HashAlgorithm.sha384, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs) } 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(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() node = node.add_child(ExpectClose()) conversations["no SHA-1"] = conversation # undefined values conversation = Connect(host, port) node = conversation sigs = [ (HashAlgorithm.sha256, 24), # undefined signature algorithm (24, SignatureAlgorithm.rsa), # undefined hash algorithm (10, 10), # undefined pair (9, 24), # undefined pair (0xff, 0xff), # undefined pair (HashAlgorithm.sha512, SignatureAlgorithm.rsa), (HashAlgorithm.sha384, SignatureAlgorithm.rsa), (HashAlgorithm.sha256, SignatureAlgorithm.rsa), (HashAlgorithm.sha224, SignatureAlgorithm.rsa) ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs) } 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(valid_sig_algs=sigs[5:])) 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() node = node.add_child(ExpectClose()) conversations["extra sigalgs"] = conversation conversation = Connect(host, port) node = conversation sigs = [ (HashAlgorithm.sha256, 24), # undefined signature algorithm (24, SignatureAlgorithm.rsa), # undefined hash algorithm (10, 10), # undefined pair (9, 24), # undefined pair (0xff, 0xff) # undefined pair ] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs) } 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( ExpectAlert(AlertLevel.fatal, AlertDescription.handshake_failure)) node = node.add_child(ExpectClose()) conversations["only undefined sigalgs"] = conversation # invalid formatting conversation = Connect(host, port) node = conversation ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create([]) } 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( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["empty sigalgs"] = conversation # invalid length conversation = Connect(host, port) node = conversation sigs = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs) } 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 ] msg = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(fuzz_message(msg, xors={-3: 1})) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["fuzz length of sigalgs"] = conversation # invalid length conversation = Connect(host, port) node = conversation sigs = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] ext = { ExtensionType.signature_algorithms: SignatureAlgorithmsExtension().create(sigs) } 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 ] msg = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(fuzz_message(msg, substitutions={-3: 4})) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["truncate sigalgs extension"] = conversation # odd length conversation = Connect(host, port) node = conversation sigs = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] ext = { ExtensionType.signature_algorithms: TLSExtension(extType=ExtensionType.signature_algorithms).create( bytearray(b'\x00\x03' # length of array b'\x04\x01' # sha256 + rsa b'\x04')) } # the odd byte 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 ] msg = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(msg) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["odd length of sigalgs"] = conversation # padded extension conversation = Connect(host, port) node = conversation sigs = [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)] ext = { ExtensionType.signature_algorithms: TLSExtension(extType=ExtensionType.signature_algorithms).create( bytearray(b'\x00\x04' # length of array b'\x02\x01' # sha1+rsa b'\x04\x01' # sha256 + rsa b'\x04\x03')) } # extra bytes 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 ] msg = ClientHelloGenerator(ciphers, extensions=ext) node = node.add_child(msg) node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.decode_error)) node = node.add_child(ExpectClose()) conversations["padded sigalgs"] = 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 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 test_write(self): tls_extension = TLSExtension() with self.assertRaises(AssertionError) as environment: tls_extension.write()