def test_SRP_key_exchange_without_signature(self): self.cipher_suite = CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA self.keyExchange.cipherSuite = self.cipher_suite self.server_hello.cipher_suite = self.cipher_suite srv_key_ex = self.keyExchange.makeServerKeyExchange() a = bytesToNumber(getRandomBytes(32)) A = powMod(srv_key_ex.srp_g, a, srv_key_ex.srp_N) x = makeX(srv_key_ex.srp_s, bytearray(b'user'), bytearray(b'password')) v = powMod(srv_key_ex.srp_g, x, srv_key_ex.srp_N) u = makeU(srv_key_ex.srp_N, A, srv_key_ex.srp_B) k = makeK(srv_key_ex.srp_N, srv_key_ex.srp_g) S = powMod((srv_key_ex.srp_B - (k*v)) % srv_key_ex.srp_N, a+(u*x), srv_key_ex.srp_N) cln_premaster = numberToByteArray(S) cln_key_ex = ClientKeyExchange(self.cipher_suite, (3, 3)).createSRP(A) srv_premaster = self.keyExchange.processClientKeyExchange(cln_key_ex) self.assertEqual(cln_premaster, srv_premaster)
def test_SRP_key_exchange(self): srv_key_ex = self.keyExchange.makeServerKeyExchange('sha256') KeyExchange.verifyServerKeyExchange(srv_key_ex, self.srv_pub_key, self.client_hello.random, self.server_hello.random, [(HashAlgorithm.sha256, SignatureAlgorithm.rsa)]) a = bytesToNumber(getRandomBytes(32)) A = powMod(srv_key_ex.srp_g, a, srv_key_ex.srp_N) x = makeX(srv_key_ex.srp_s, bytearray(b'user'), bytearray(b'password')) v = powMod(srv_key_ex.srp_g, x, srv_key_ex.srp_N) u = makeU(srv_key_ex.srp_N, A, srv_key_ex.srp_B) k = makeK(srv_key_ex.srp_N, srv_key_ex.srp_g) S = powMod((srv_key_ex.srp_B - (k*v)) % srv_key_ex.srp_N, a+(u*x), srv_key_ex.srp_N) cln_premaster = numberToByteArray(S) cln_key_ex = ClientKeyExchange(self.cipher_suite, (3, 3)).createSRP(A) srv_premaster = self.keyExchange.processClientKeyExchange(cln_key_ex) self.assertEqual(cln_premaster, srv_premaster)
def test_with_invalid_random_hash(self, i): key = compatHMAC(getRandomBytes(20)) seqnum_bytes = bytearray(16) content_type = 0x15 version = (3, 3) application_data = getRandomBytes(63) mac = hashlib.sha1 data = self.data_prepare(application_data, seqnum_bytes, content_type, version, mac, key) data[-i] ^= 0xff padding = bytearray(b'\x00') data += padding h = hmac.new(key, digestmod=mac) h.block_size = mac().block_size self.assertFalse(ct_check_cbc_mac_and_pad(data, h, seqnum_bytes, content_type, version))
def generate(self, state): """Generate a new CLIENT-MASTER-KEY message.""" if self.cipher is None: raise NotImplementedError("No cipher autonegotiation") if self.master_key is None: if state.master_secret == bytearray(0): if self.cipher in CipherSuite.ssl2_128Key: key_size = 16 elif self.cipher in CipherSuite.ssl2_192Key: key_size = 24 elif self.cipher in CipherSuite.ssl2_64Key: key_size = 8 else: raise AssertionError("unknown cipher but no master_secret") self.master_key = getRandomBytes(key_size) else: self.master_key = state.master_secret cipher = self.cipher if (cipher not in CipherSuite.ssl2rc4 and cipher not in CipherSuite.ssl2_3des): # tlslite-ng doesn't implement anything else, so we need to # workaround calculation of pending states failure for test # cases which don't really encrypt data cipher = CipherSuite.SSL_CK_RC4_128_WITH_MD5 key_arg = state.msg_sock.calcSSL2PendingStates(cipher, self.master_key, state.client_random, state.server_random, None) if self.cipher in CipherSuite.ssl2export: clear_key = self.master_key[:-5] secret_key = self.master_key[-5:] else: clear_key = bytearray(0) secret_key = self.master_key pub_key = state.get_server_public_key() encrypted_master_key = pub_key.encrypt(secret_key) cmk = ClientMasterKey() cmk.create(self.cipher, clear_key, encrypted_master_key, key_arg) self.msg = cmk return cmk
def test_DHE_RSA_key_exchange(self): srv_key_ex = self.keyExchange.makeServerKeyExchange('sha1') cln_X = bytesToNumber(getRandomBytes(32)) cln_Yc = powMod(srv_key_ex.dh_g, cln_X, srv_key_ex.dh_p) cln_secret = numberToByteArray(powMod(srv_key_ex.dh_Ys, cln_X, srv_key_ex.dh_p)) cln_key_ex = ClientKeyExchange(self.cipher_suite, (3, 3)) cln_key_ex.createDH(cln_Yc) srv_secret = self.keyExchange.processClientKeyExchange(cln_key_ex) self.assertEqual(cln_secret, srv_secret)
def serverCmd(argv): (address, privateKey, cert_chain, tacks, verifierDB, directory, reqCert, expLabel, expLength, dhparam, psk, psk_ident, psk_hash) = \ handleArgs(argv, "kctbvdlL", ["reqcert", "param=", "psk=", "psk-ident=", "psk-sha384"]) if (cert_chain and not privateKey) or (not cert_chain and privateKey): raise SyntaxError("Must specify CERT and KEY together") if tacks and not cert_chain: raise SyntaxError("Must specify CERT with Tacks") print("I am an HTTPS test server, I will listen on %s:%d" % (address[0], address[1])) if directory: os.chdir(directory) print("Serving files from %s" % os.getcwd()) if cert_chain and privateKey: print("Using certificate and private key...") if verifierDB: print("Using verifier DB...") if tacks: print("Using Tacks...") if reqCert: print("Asking for client certificates...") ############# sessionCache = SessionCache() username = None sni = None if is_valid_hostname(address[0]): sni = address[0] settings = HandshakeSettings() settings.useExperimentalTackExtension = True settings.dhParams = dhparam if psk: settings.pskConfigs = [(psk_ident, psk, psk_hash)] settings.ticketKeys = [getRandomBytes(32)] class MySimpleHTTPHandler(SimpleHTTPRequestHandler): """Buffer the header and body of HTTP message.""" wbufsize = -1 class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer): def handshake(self, connection): print("About to handshake...") activationFlags = 0 if tacks: if len(tacks) == 1: activationFlags = 1 elif len(tacks) == 2: activationFlags = 3 try: start = time.clock() connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) connection.handshakeServer(certChain=cert_chain, privateKey=privateKey, verifierDB=verifierDB, tacks=tacks, activationFlags=activationFlags, sessionCache=sessionCache, settings=settings, nextProtos=[b"http/1.1"], alpn=[bytearray(b'http/1.1')], reqCert=reqCert, sni=sni) # As an example (does not work here): #nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"]) stop = time.clock() except TLSRemoteAlert as a: if a.description == AlertDescription.user_canceled: print(str(a)) return False else: raise except TLSLocalAlert as a: if a.description == AlertDescription.unknown_psk_identity: if username: print("Unknown username") return False else: raise elif a.description == AlertDescription.bad_record_mac: if username: print("Bad username or password") return False else: raise elif a.description == AlertDescription.handshake_failure: print("Unable to negotiate mutually acceptable parameters") return False else: raise connection.ignoreAbruptClose = True printGoodConnection(connection, stop - start) printExporter(connection, expLabel, expLength) return True httpd = MyHTTPServer(address, MySimpleHTTPHandler) httpd.serve_forever()
def main(): host = "localhost" port = 4433 num_limit = None run_exclude = set() num_bytes = 2**14 cookie = False argv = sys.argv[1:] opts, args = getopt.getopt(argv, "h:p:e:n:", ["help", "num-bytes=", "cookie"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '--help': help_msg() sys.exit(0) elif opt == '--num-bytes': num_bytes = int(arg) elif opt == '--cookie': cookie = True else: raise ValueError("Unknown option: {0}".format(opt)) if args: run_only = set(args) else: run_only = None conversations = {} # sanity check conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = {} groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["sanity"] = conversation # sanity check with PSK binders conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), 0) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid PSK"] = conversation # fake 0-RTT resumption with HRR and early data after second client hello conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [0x1300, GroupName.secp256r1] key_shares = [KeyShareEntry().create(0x1300, bytearray(b'\xab' * 32))] ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) ext = {} if cookie: ext[ExtensionType.cookie] = None ext[ExtensionType.key_share] = None ext[ExtensionType.supported_versions] = None node = node.add_child(ExpectHelloRetryRequest(extensions=ext)) node = node.add_child(ExpectChangeCipherSpec()) ext = OrderedDict() key_shares = [] for group in [GroupName.secp256r1]: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) if cookie: ext[ExtensionType.cookie] = ch_cookie_handler ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create( [iden], [getRandomBytes(32)]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child( PlaintextMessageGenerator(ContentType.application_data, getRandomBytes(64))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac) node.next_sibling.add_child(ExpectClose()) conversations["handshake with 0-RTT, HRR and early data after 2nd Client Hello"]\ = conversation # fake 0-RTT resumption with HRR conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [0x1300, GroupName.secp256r1] key_shares = [KeyShareEntry().create(0x1300, bytearray(b'\xab' * 32))] ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) ext = {} if cookie: ext[ExtensionType.cookie] = None ext[ExtensionType.key_share] = None ext[ExtensionType.supported_versions] = None node = node.add_child(ExpectHelloRetryRequest(extensions=ext)) node = node.add_child(ExpectChangeCipherSpec()) ext = OrderedDict() key_shares = [] for group in [GroupName.secp256r1]: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) if cookie: ext[ExtensionType.cookie] = ch_cookie_handler ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create( [iden], [getRandomBytes(32)]) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT and HRR"] = conversation # fake 0-RTT resumption with fragmented early data conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT with fragmented early data"]\ = conversation # fake 0-RTT and early data spliced into the Finished message conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) finished_fragments = [] node = node.add_child( split_message(FinishedGenerator(), finished_fragments, 16)) # early data spliced into the Finished message node = node.add_child( PlaintextMessageGenerator(ContentType.application_data, getRandomBytes(64))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectAlert(AlertLevel.fatal, AlertDescription.bad_record_mac) node.next_sibling.add_child(ExpectClose()) conversations["undecryptable record later in handshake together with early_data"]\ = conversation # fake 0-RTT resumption and CCS between fake early data conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child(ChangeCipherSpecGenerator(fake=True)) node = node.add_child( ApplicationDataGenerator(getRandomBytes(num_bytes // 2))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT and CCS between early data records"]\ = conversation # fake 0-RTT resumption and CCS conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ChangeCipherSpecGenerator(fake=True)) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT and CCS"] = conversation # fake 0-RTT resumption with unknown version conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([(3, 5), (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello(version=(3, 3))) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectServerHelloDone()) # section D.3 of draft 28 states that client that receives TLS 1.2 # ServerHello as a reply to 0-RTT Client Hello MUST fail a connection # consequently, the server does not need to be able to ignore early data # in TLS 1.2 mode node = node.add_child( ExpectAlert(AlertLevel.fatal, AlertDescription.unexpected_message)) node.add_child(ExpectClose()) conversations[ "handshake with invalid 0-RTT and unknown version (downgrade to TLS 1.2)"] = conversation # fake 0-RTT resumption conversation = Connect(host, port) node = conversation ciphers = [ CipherSuite.TLS_AES_128_GCM_SHA256, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV ] ext = OrderedDict() groups = [GroupName.secp256r1] key_shares = [] for group in groups: key_shares.append(key_share_gen(group)) ext[ExtensionType.key_share] = ClientKeyShareExtension().create(key_shares) ext[ExtensionType.supported_versions] = SupportedVersionsExtension()\ .create([TLS_1_3_DRAFT, (3, 3)]) ext[ExtensionType.supported_groups] = SupportedGroupsExtension()\ .create(groups) sig_algs = [ SignatureScheme.rsa_pss_rsae_sha256, SignatureScheme.rsa_pss_pss_sha256 ] ext[ExtensionType.signature_algorithms] = SignatureAlgorithmsExtension()\ .create(sig_algs) ext[ExtensionType.signature_algorithms_cert] = SignatureAlgorithmsCertExtension()\ .create(RSA_SIG_ALL) ext[ExtensionType.early_data] = \ TLSExtension(extType=ExtensionType.early_data) ext[ExtensionType.psk_key_exchange_modes] = PskKeyExchangeModesExtension()\ .create([PskKeyExchangeMode.psk_dhe_ke, PskKeyExchangeMode.psk_ke]) iden = PskIdentity().create(getRandomBytes(320), getRandomNumber(2**30, 2**32)) bind = getRandomBytes(32) ext[ExtensionType.pre_shared_key] = PreSharedKeyExtension().create([iden], [bind]) node = node.add_child(TCPBufferingEnable()) node = node.add_child(ClientHelloGenerator(ciphers, extensions=ext)) node = node.add_child(SetRecordVersion((3, 3))) node = node.add_child(ApplicationDataGenerator(getRandomBytes(num_bytes))) node = node.add_child(TCPBufferingDisable()) node = node.add_child(TCPBufferingFlush()) node = node.add_child(ExpectServerHello()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectEncryptedExtensions()) node = node.add_child(ExpectCertificate()) node = node.add_child(ExpectCertificateVerify()) node = node.add_child(ExpectFinished()) node = node.add_child(FinishedGenerator()) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\r\n\r\n"))) # This message is optional and may show up 0 to many times cycle = ExpectNewSessionTicket() node = node.add_child(cycle) node.add_child(cycle) node.next_sibling = ExpectApplicationData() node = node.next_sibling.add_child( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child(ExpectAlert()) node.next_sibling = ExpectClose() conversations["handshake with invalid 0-RTT"] = conversation # run the conversation good = 0 bad = 0 failed = [] if not num_limit: num_limit = len(conversations) # make sure that sanity test is run first and last # to verify that server was running and kept running throught sanity_test = ('sanity', conversations['sanity']) ordered_tests = chain([sanity_test], islice( filter(lambda x: x[0] != 'sanity', conversations.items()), num_limit), [sanity_test]) for c_name, c_test in ordered_tests: if run_only and c_name not in run_only or c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(c_test) res = True try: runner.run() except Exception: print("Error while processing") print(traceback.format_exc()) res = False if res: good += 1 print("OK\n") else: bad += 1 failed.append(c_name) print("Basic check if TLS 1.3 server can handle 0-RTT handshake") print("Verify that the server can handle a 0-RTT handshake from client") print("even if (or rather, especially if) it doesn't support 0-RTT.\n") print("version: {0}\n".format(version)) print("Test end") print("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 serverCmd(argv): (address, privateKey, cert_chain, tacks, verifierDB, directory, reqCert, expLabel, expLength, dhparam, psk, psk_ident, psk_hash, ssl3, max_ver, tickets) = \ handleArgs(argv, "kctbvdlL", ["reqcert", "param=", "psk=", "psk-ident=", "psk-sha384", "ssl3", "max-ver=", "tickets="]) if (cert_chain and not privateKey) or (not cert_chain and privateKey): raise SyntaxError("Must specify CERT and KEY together") if tacks and not cert_chain: raise SyntaxError("Must specify CERT with Tacks") print("I am an HTTPS test server, I will listen on %s:%d" % (address[0], address[1])) if directory: os.chdir(directory) print("Serving files from %s" % os.getcwd()) if cert_chain and privateKey: print("Using certificate and private key...") if verifierDB: print("Using verifier DB...") if tacks: print("Using Tacks...") if reqCert: print("Asking for client certificates...") ############# sessionCache = SessionCache() username = None sni = None if is_valid_hostname(address[0]): sni = address[0] settings = HandshakeSettings() settings.useExperimentalTackExtension=True settings.dhParams = dhparam if tickets is not None: settings.ticket_count = tickets if psk: settings.pskConfigs = [(psk_ident, psk, psk_hash)] settings.ticketKeys = [getRandomBytes(32)] if ssl3: settings.minVersion = (3, 0) if max_ver: settings.maxVersion = max_ver class MySimpleHTTPHandler(SimpleHTTPRequestHandler): """Buffer the header and body of HTTP message.""" wbufsize = -1 class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer): def handshake(self, connection): print("About to handshake...") activationFlags = 0 if tacks: if len(tacks) == 1: activationFlags = 1 elif len(tacks) == 2: activationFlags = 3 try: start = time_stamp() connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) connection.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 5)) connection.handshakeServer(certChain=cert_chain, privateKey=privateKey, verifierDB=verifierDB, tacks=tacks, activationFlags=activationFlags, sessionCache=sessionCache, settings=settings, nextProtos=[b"http/1.1"], alpn=[bytearray(b'http/1.1')], reqCert=reqCert, sni=sni) # As an example (does not work here): #nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"]) stop = time_stamp() except TLSRemoteAlert as a: if a.description == AlertDescription.user_canceled: print(str(a)) return False else: raise except TLSLocalAlert as a: if a.description == AlertDescription.unknown_psk_identity: if username: print("Unknown username") return False else: raise elif a.description == AlertDescription.bad_record_mac: if username: print("Bad username or password") return False else: raise elif a.description == AlertDescription.handshake_failure: print("Unable to negotiate mutually acceptable parameters") return False else: raise connection.ignoreAbruptClose = True printGoodConnection(connection, stop-start) printExporter(connection, expLabel, expLength) return True httpd = MyHTTPServer(address, MySimpleHTTPHandler) httpd.serve_forever()
def serverCmd(argv): (address, privateKey, cert_chain, virtual_hosts, tacks, verifierDB, directory, reqCert, expLabel, expLength, dhparam, psk, psk_ident, psk_hash, ssl3, max_ver, tickets, cipherlist, request_pha, require_pha) = \ handleArgs(argv, "kctbvdlL", ["reqcert", "param=", "psk=", "psk-ident=", "psk-sha384", "ssl3", "max-ver=", "tickets=", "cipherlist=", "request-pha", "require-pha"]) if (cert_chain and not privateKey) or (not cert_chain and privateKey): raise SyntaxError("Must specify CERT and KEY together") if tacks and not cert_chain: raise SyntaxError("Must specify CERT with Tacks") print("I am an HTTPS test server, I will listen on %s:%d" % (address[0], address[1])) if directory: os.chdir(directory) print("Serving files from %s" % os.getcwd()) if cert_chain and privateKey: print("Using certificate and private key...") if verifierDB: print("Using verifier DB...") if tacks: print("Using Tacks...") if reqCert: print("Asking for client certificates...") ############# sessionCache = SessionCache() username = None sni = None if is_valid_hostname(address[0]): sni = address[0] settings = HandshakeSettings() settings.useExperimentalTackExtension = True settings.dhParams = dhparam if tickets is not None: settings.ticket_count = tickets if psk: settings.pskConfigs = [(psk_ident, psk, psk_hash)] settings.ticketKeys = [getRandomBytes(32)] if ssl3: settings.minVersion = (3, 0) if max_ver: settings.maxVersion = max_ver settings.virtual_hosts = virtual_hosts if cipherlist: settings.cipherNames = [ item for cipher in cipherlist for item in cipher.split(',') ] class MySimpleHTTPHandler(SimpleHTTPRequestHandler, object): """Buffer the header and body of HTTP message.""" wbufsize = -1 def do_GET(self): """Simple override to send KeyUpdate to client.""" if self.path.startswith('/keyupdate'): for i in self.connection.send_keyupdate_request( KeyUpdateMessageType.update_requested): if i in (0, 1): continue else: raise ValueError("Invalid return from " "send_keyupdate_request") if self.path.startswith('/secret') and not request_pha: try: for i in self.connection.request_post_handshake_auth(): pass except ValueError: self.wfile.write(b'HTTP/1.0 401 Certificate authentication' b' required\r\n') self.wfile.write(b'Connection: close\r\n') self.wfile.write(b'Content-Length: 0\r\n\r\n') return self.connection.read(0, 0) if self.connection.session.clientCertChain: print(" Got client certificate in post-handshake auth: " "{0}".format(self.connection.session.clientCertChain. getFingerprint())) else: print(" No certificate from client received") self.wfile.write(b'HTTP/1.0 401 Certificate authentication' b' required\r\n') self.wfile.write(b'Connection: close\r\n') self.wfile.write(b'Content-Length: 0\r\n\r\n') return return super(MySimpleHTTPHandler, self).do_GET() class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer): def handshake(self, connection): print("About to handshake...") activationFlags = 0 if tacks: if len(tacks) == 1: activationFlags = 1 elif len(tacks) == 2: activationFlags = 3 try: start = time_stamp() connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) connection.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 5)) connection.client_cert_required = require_pha connection.handshakeServer(certChain=cert_chain, privateKey=privateKey, verifierDB=verifierDB, tacks=tacks, activationFlags=activationFlags, sessionCache=sessionCache, settings=settings, nextProtos=[b"http/1.1"], alpn=[bytearray(b'http/1.1')], reqCert=reqCert, sni=sni) # As an example (does not work here): #nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"]) try: if request_pha: for i in connection.request_post_handshake_auth(): pass except ValueError: # if we can't do PHA, we can't do it pass stop = time_stamp() except TLSRemoteAlert as a: if a.description == AlertDescription.user_canceled: print(str(a)) return False else: raise except TLSLocalAlert as a: if a.description == AlertDescription.unknown_psk_identity: if username: print("Unknown username") return False else: raise elif a.description == AlertDescription.bad_record_mac: if username: print("Bad username or password") return False else: raise elif a.description == AlertDescription.handshake_failure: print("Unable to negotiate mutually acceptable parameters") return False else: raise connection.ignoreAbruptClose = True printGoodConnection(connection, stop - start) printExporter(connection, expLabel, expLength) return True httpd = MyHTTPServer(address, MySimpleHTTPHandler) httpd.serve_forever()
def serverCmd(argv): (address, privateKey, cert_chain, tacks, verifierDB, directory, reqCert, fido2_db, fido2_db_encryption_key, fido2_modes, force_fido2, pre_share_eph_user_name, expLabel, expLength, dhparam, psk, psk_ident, psk_hash, ssl3,max_ver, tickets, verbose) = \ handleArgs(argv, "kctbvdlL", ["reqcert", "fido2-db=", "db-encryption-key=", "fido2-modes=", "force-fido2", "pre-share-euname", "param=", "psk=", "psk-ident=", "psk-sha384", "ssl3", "max-ver=", "tickets=", "verbose"]) if (cert_chain and not privateKey) or (not cert_chain and privateKey): raise SyntaxError("Must specify CERT and KEY together") if tacks and not cert_chain: raise SyntaxError("Must specify CERT with Tacks") print("I am an HTTPS test server, I will listen on %s:%d" % (address[0], address[1])) if directory: os.chdir(directory) print("Serving files from %s" % os.getcwd()) if cert_chain and privateKey: print("Using certificate and private key...") if verifierDB: print("Using verifier DB...") if tacks: print("Using Tacks...") if reqCert: print("Asking for client certificates...") fido2_params = None if fido2_db: print("Using FIDO2 authentication...") fido2_params = { 'db_path': fido2_db, 'rp_id': address[0], 'db_encryption_key': fido2_db_encryption_key, 'modes': fido2_modes, 'pre_share_eph_user_name': pre_share_eph_user_name, 'force': force_fido2 } ############# sessionCache = SessionCache() username = None sni = None if is_valid_hostname(address[0]): sni = address[0] settings = HandshakeSettings() settings.useExperimentalTackExtension = True settings.dhParams = dhparam settings.ticket_count = tickets or settings.ticket_count if psk: settings.pskConfigs = [(psk_ident, psk, psk_hash)] settings.ticketKeys = [getRandomBytes(32)] if ssl3: settings.minVersion = (3, 0) if max_ver: settings.maxVersion = max_ver if fido2_db and settings.maxVersion < (3, 4): raise Exception("FIDO2 authentication requres TLS 1.3 support") if fido2_db and force_fido2: settings.force_fido2_extension = True class MySimpleHTTPHandler(SimpleHTTPRequestHandler): """Buffer the header and body of HTTP message.""" wbufsize = -1 class MyHTTPServer(ThreadingMixIn, TLSSocketServerMixIn, HTTPServer): def __init__(self, address, request_handhler): HTTPServer.__init__(self, address, request_handhler) def handshake(self, connection): print("About to handshake...") activationFlags = 0 if tacks: if len(tacks) == 1: activationFlags = 1 elif len(tacks) == 2: activationFlags = 3 try: start = time_stamp() if verbose: connection.set_verbose() connection.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) connection.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 5)) connection.handshakeServer(certChain=cert_chain, privateKey=privateKey, verifierDB=verifierDB, tacks=tacks, activationFlags=activationFlags, sessionCache=sessionCache, settings=settings, nextProtos=[b"http/1.1"], alpn=[bytearray(b'http/1.1')], reqCert=reqCert, fido2_params=fido2_params, sni=sni) # As an example (does not work here): # nextProtos=[b"spdy/3", b"spdy/2", b"http/1.1"]) stop = time_stamp() except TLSRemoteAlert as a: if a.description == AlertDescription.user_canceled: print(str(a)) return False elif a.description == AlertDescription.fido2_bad_request: print("Bad FIDO2 request sent") return False else: raise except TLSLocalAlert as a: if a.description == AlertDescription.unknown_psk_identity: if username: print("Unknown username") return False else: raise elif a.description == AlertDescription.bad_record_mac: if username: print("Bad username or password") return False else: raise elif a.description == AlertDescription.handshake_failure: print("Unable to negotiate mutually acceptable parameters") return False elif a.description == \ AlertDescription.fido2_authentication_error: print("FIDO2 authentication failed") return False else: raise connection.ignoreAbruptClose = True printGoodConnection(connection, stop - start) printExporter(connection, expLabel, expLength) return True httpd = MyHTTPServer(address, MySimpleHTTPHandler) httpd.serve_forever()
def conv_generator(conf, host, port, sni_hostname, cert=None, key=None): """Generate a conversation based on dict with configuration.""" root = Connect(host, port) hs = HandshakeSettings() # only RSA is supported if conf['Server_authentication'] != "RSA" and \ conf['Server_authentication'] != "anon": print("Substituting {0} to RSA for server auth".format( conf['Server_authentication']), file=sys.stderr) # get the cipher that matches the imposed restrictions cipher_trans = { "AES_128_CBC": "aes128", "AES_256_CBC": "aes256", "AES_128_GCM": "aes128gcm", "AES_256_GCM": "aes256gcm", "3DES_EDE_CBC": "3des", "RC4": "rc4", "Chacha20_Poly1305": "chacha20-poly1305" } hs.cipherNames = [cipher_trans.get(conf['Cipher'], None)] if hs.cipherNames == [None]: raise ValueError("Unknown cipher type: {0}".format(conf['Cipher'])) mac_trans = { "AEAD": "aead", "MD5_HMAC": "md5", "SHA1_HMAC": "sha", "SHA256_HMAC": "sha256", "SHA384_HMAC": "sha384" } hs.macNames = [mac_trans.get(conf['Integrity'], None)] if hs.macNames == [None]: raise ValueError("Unknown integrity type: {0}".format( conf['Integrity'])) if conf['Key_exchange'] == 'DHE' and \ conf['Server_authentication'] == "anon": suites = CipherSuite.getAnonSuites(hs) elif conf['Key_exchange'] == 'ECDHE' and \ conf['Server_authentication'] == "anon": suites = CipherSuite.getEcdhAnonSuites(hs) elif conf['Key_exchange'] == 'RSA': suites = CipherSuite.getCertSuites(hs) elif conf['Key_exchange'] == 'DHE': suites = CipherSuite.getDheCertSuites(hs) elif conf['Key_exchange'] == 'ECDHE': suites = CipherSuite.getEcdheCertSuites(hs) else: raise ValueError("Unknown key exchange type: {0}".format( conf['Key_exchange'])) if not suites: raise ValueError( "Couldn't find matching cipher for {0} {3} {1} {2}".format( conf['Key_exchange'], conf['Cipher'], conf['Integrity'], conf['Server_authentication'])) # session ID/resumption handling if conf['CH_SessionID'] == 'random': sess_ID = getRandomBytes(16) elif conf['CH_SessionID'] == 'empty': sess_ID = bytearray() else: raise ValueError("Unknown CH_SessionID value".format( conf['CH_SessionID'])) # compression if conf['CH_compression'] == 'null_only': compress = [0] elif conf['CH_compression'] == 'null_and_deflate': compress = [0, 1] else: raise ValueError("Unknown CH_compression value: {0}".format( conf['CH_compression'])) # Renegotiation Info if conf['CH_renegotiation_info_SCSV'] == "first": suites.insert(0, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) elif conf['CH_renegotiation_info_SCSV'] == "last": suites.append(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) elif conf['CH_renegotiation_info_SCSV'] == "absent": pass elif conf['CH_renegotiation_info_SCSV'] == "second": suites.append(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) suites.append(0xeaea) # GREASE else: raise ValueError( "Unexpected CH_renegotiation_info_SCSV value: {0}".format( conf['CH_renegotiation_info_SCSV'])) # whether to send extensions if conf['CH_extensions_present'] == "false": ext = None elif conf['CH_extensions_present'] != "true": raise ValueError("Unexpected CH_extensions_present value: {0}".format( conf['CH_extensions_present'])) else: ext = dict() # session ticket if conf['CH_session_ticket'] != "no_ext": print("Not generating session ticket extension", file=sys.stderr) # renegotiation info if conf['CH_renegotiation_info_ext'] == "true": ext[ExtensionType.renegotiation_info] = \ RenegotiationInfoExtension().create(bytearray()) elif conf['CH_renegotiation_info_ext'] == "false": pass else: raise ValueError( "Unknown option in CH_renegotiation_info_ext: {0}".format( conf['CH_renegotiation_info_ext'])) # signature algorithms if conf['CH_signature_algorithms_ext'] == "false": pass elif conf['CH_signature_algorithms_ext'] != "true": raise ValueError( "Unknown option CH_signature_algorithms_ext: {0}".format( conf["CH_signature_algorithms_ext"])) else: sig = conf['SKE_signature_scheme'] if sig == "none" or sig == "no_message": # enter some random ones: ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension()\ .create([SignatureScheme.rsa_pkcs1_sha256, SignatureScheme.rsa_pss_sha256]) else: if "dsa" in sig: print("Changing {0} to RSA scheme".format(sig)) sig = sig.replace("ecdsa", "rsa") sig = sig.replace("dsa", "rsa") sig = sig.replace("rsa_sha", "rsa_pkcs1_sha") sig = sig.replace("rsapss", "rsa_pss") if "sha224" in sig: scheme = (HashAlgorithm.sha224, SignatureAlgorithm.rsa) else: scheme = getattr(SignatureScheme, sig) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension()\ .create([scheme]) # supported groups extension if conf['CH_supported_groups_ext'] == "false": groups = [ GroupName.ffdhe2048, GroupName.secp256r1, GroupName.x25519 ] ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) pass elif conf['CH_supported_groups_ext'] != "true": raise ValueError( "Unknown option in CH_supported_groups_ext: {0}".format( conf['CH_supported_groups_ext'])) else: if conf['SKE_dh_group'] == "no_message": groups = [ GroupName.ffdhe2048, GroupName.secp256r1, GroupName.x25519 ] elif conf['SKE_dh_group'] == "ffdhe1024": groups = [GroupName.secp256r1, GroupName.x25519] else: groups = [getattr(GroupName, conf['SKE_dh_group'])] ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.ec_point_formats] = \ ECPointFormatsExtension()\ .create([ECPointFormat.uncompressed, ECPointFormat.ansiX962_compressed_char2, ECPointFormat.ansiX962_compressed_prime]) # encrypt then MAC if conf['CH_encrypt_then_mac_ext'] == "false": pass elif conf['CH_encrypt_then_mac_ext'] != "true": raise ValueError( "Unknown option in CH_encrypt_then_mac_ext: {0}".format( conf['CH_encrypt_then_mac_ext'])) else: ext[ExtensionType.encrypt_then_mac] = \ TLSExtension(extType=ExtensionType.encrypt_then_mac)\ .create(bytearray(0)) # server name if conf['CH_server_name'] == "no_ext": pass elif conf['CH_server_name'] == "correct": ext[ExtensionType.server_name] = \ SNIExtension().create(sni_hostname) elif conf['CH_server_name'] == "mismatch": ext[ExtensionType.server_name] = \ SNIExtension().create(sni_hostname + b'.www') else: raise ValueError("Unknown option in CH_server_name: {0}".format( conf['CH_server_name'])) # OCSP staple if conf['CH_status_request_ext'] == "false": pass elif conf['CH_status_request_ext'] != "true": raise ValueError( "Unknown option in CH_status_request_ext: {0}".format( conf['CH_status_request_ext'])) else: ext[ExtensionType.status_request] = \ StatusRequestExtension().create() # Extended Master Secret ext if conf['CH_extended_master_secret_ext'] == "false": pass elif conf['CH_extended_master_secret_ext'] != "true": raise ValueError( ("Unknown value in CH_extended_master_secret_ext" ": {0}").format(conf['CH_extended_master_secret_ext'])) else: ext[ExtensionType.extended_master_secret] = \ TLSExtension(extType=ExtensionType.extended_master_secret)\ .create(bytearray()) # # node = root.add_child( ClientHelloGenerator(suites, session_id=sess_ID, compression=compress, extensions=ext)) if conf['CH_server_name'] == "mismatch": node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.unrecognized_name)) al_node = node node = node.add_child(ExpectServerHello()) if conf['CH_server_name'] == "mismatch": # make the sending of warning alert node optional al_node.next_sibling = node node = node.add_child(ExpectCertificate()) # TODO if conf['Certificate_Status_msg'] if conf['SKE_dh_group'] != "no_message": node = node.add_child(ExpectServerKeyExchange()) if conf['CR_sent'] == "true": node = node.add_child(ExpectCertificateRequest()) elif conf['CR_sent'] != "false": raise ValueError("Unknown option in CR_sent: {0}".format( conf['CR_sent'])) node = node.add_child(ExpectServerHelloDone()) if conf['CR_sent'] == "true": if conf['CV_signature_scheme'] == "no_message": node = node.add_child(CertificateGenerator()) else: node = node.add_child(CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) if conf['CV_signature_scheme'] != "no_message": sig = conf['CV_signature_scheme'] if "dsa" in sig: print("Changing {0} to RSA scheme in CV".format(sig)) sig = sig.replace("ecdsa", "rsa") sig = sig.replace("dsa", "rsa") sig = sig.replace("rsa_sha", "rsa_pkcs1_sha") sig = sig.replace("rsapss", "rsa_pss") if "sha224" in sig: scheme = (HashAlgorithm.sha224, SignatureAlgorithm.rsa) else: scheme = getattr(SignatureScheme, sig) node = node.add_child(CertificateVerifyGenerator(key, msg_alg=scheme)) node = node.add_child(ChangeCipherSpecGenerator()) node = node.add_child(FinishedGenerator()) node = node.add_child(ExpectChangeCipherSpec()) node = node.add_child(ExpectFinished()) if conf['Disconnect'] == "true": 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(node.next_sibling) node = node.add_child(Connect(host, port)) node = node.add_child(ResetRenegotiationInfo()) node = node.add_child(ResetHandshakeHashes()) hs = HandshakeSettings() hs.cipherNames = [cipher_trans.get(conf['H2Cipher'], None)] if hs.cipherNames == [None]: raise ValueError("Unknown cipher type: {0}".format(conf['H2Cipher'])) hs.macNames = [mac_trans.get(conf["H2Integrity"], None)] if hs.macNames == [None]: raise ValueError("Unknown integrity type: {0}".format( conf['H2Integrity'])) if conf['H2Key_exchange'] == 'DHE' and \ conf['H2Server_authentication'] == "anon": suites = CipherSuite.getAnonSuites(hs) elif conf['H2Key_exchange'] == "ECDHE" and \ conf['H2Server_authentication'] == "anon": suites = CipherSuite.getEcdhAnonSuites(hs) elif conf['H2Key_exchange'] == "RSA": suites = CipherSuite.getCertSuites(hs) elif conf['H2Key_exchange'] == "DHE": suites = CipherSuite.getDheCertSuites(hs) elif conf['H2Key_exchange'] == "ECDHE": suites = CipherSuite.getEcdheCertSuites(hs) else: raise ValueError("Unknown key exchange type: {0}".format( conf['H2Key_exchange'])) if not suites: raise ValueError( "Couldn't find matching cipher for {0} {3} {1} {2}".format( conf['H2Key_exchange'], conf['H2Cipher'], conf['H2Integrity'], conf['H2Server_authentication'])) if conf['H2CH_SessionID'] == 'random': sess_ID = getRandomBytes(16) elif conf['H2CH_SessionID'] == 'empty': sess_ID = bytearray() elif conf['H2CH_SessionID'] == "resume": sess_ID = None else: raise ValueError("Unknown session id value: {0}".format( conf['H2CH_SessionID'])) # compression if conf['H2CH_compression'] == 'null_only': compress = [0] elif conf['H2CH_compression'] == 'null_and_deflate': compress = [0, 1] else: raise ValueError("Unknown H2CH_compression value: {0}".format( conf['H2CH_compression'])) # Renegotiation Info if conf['H2CH_renegotiation_info_SCSV'] == "first": suites.insert(0, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) elif conf['H2CH_renegotiation_info_SCSV'] == "last": suites.append(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) elif conf['H2CH_renegotiation_info_SCSV'] == "absent": pass elif conf['H2CH_renegotiation_info_SCSV'] == "second": suites.append(CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV) suites.append(0xeaea) # GREASE else: raise ValueError( "Unexpected H2CH_renegotiation_info_SCSV value: {0}".format( conf['H2CH_renegotiation_info_SCSV'])) # whether to send extensions if conf['H2CH_extensions_present'] == "false": ext = None elif conf['H2CH_extensions_present'] != "true": raise ValueError("Unexpected CH_extensions_present value: {0}".format( conf['H2CH_extensions_present'])) else: ext = dict() # session ticket if conf['H2CH_session_ticket'] != "no_ext": print("Not generating session ticket extension", file=sys.stderr) # renegotiation info if conf['H2CH_renegotiation_info_ext'] == "true": ext[ExtensionType.renegotiation_info] = None elif conf['H2CH_renegotiation_info_ext'] == "false": pass else: raise ValueError("Unknown option in H2CH_renegotiation_info_ext: " "{0}".format(conf['H2CH_renegotiation_info_ext'])) # signature algorithms if conf['H2CH_signature_algorithms_ext'] == "false": pass elif conf['H2CH_signature_algorithms_ext'] != "true": raise ValueError("Unknown option H2CH_signature_algorithms_ext: " "{0}".format( conf["H2CH_signature_algorithms_ext"])) else: sig = conf['H2SKE_signature_scheme'] if sig == "none" or sig == "no_message": # enter some random ones: ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension()\ .create([SignatureScheme.rsa_pkcs1_sha256, SignatureScheme.rsa_pss_sha256]) else: if "dsa" in sig: print("Changing {0} to RSA scheme".format(sig)) sig = sig.replace("ecdsa", "rsa") sig = sig.replace("dsa", "rsa") sig = sig.replace("rsa_sha", "rsa_pkcs1_sha") sig = sig.replace("rsapss", "rsa_pss") if "sha224" in sig: scheme = (HashAlgorithm.sha224, SignatureAlgorithm.rsa) else: scheme = getattr(SignatureScheme, sig) ext[ExtensionType.signature_algorithms] = \ SignatureAlgorithmsExtension()\ .create([scheme]) # supported groups extension if conf['H2CH_supported_groups_ext'] == "false": groups = [ GroupName.ffdhe2048, GroupName.secp256r1, GroupName.x25519 ] ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) pass elif conf['H2CH_supported_groups_ext'] != "true": raise ValueError( "Unknown option in H2CH_supported_groups_ext: {0}".format( conf['H2CH_supported_groups_ext'])) else: if conf['H2SKE_dh_group'] == "no_message": groups = [ GroupName.ffdhe2048, GroupName.secp256r1, GroupName.x25519 ] elif conf['H2SKE_dh_group'] == "ffdhe1024": groups = [GroupName.secp256r1, GroupName.x25519] else: groups = [getattr(GroupName, conf['H2SKE_dh_group'])] ext[ExtensionType.supported_groups] = \ SupportedGroupsExtension().create(groups) ext[ExtensionType.ec_point_formats] = \ ECPointFormatsExtension()\ .create([ECPointFormat.uncompressed, ECPointFormat.ansiX962_compressed_char2, ECPointFormat.ansiX962_compressed_prime]) # encrypt then MAC if conf['H2CH_encrypt_then_mac_ext'] == "false": pass elif conf['H2CH_encrypt_then_mac_ext'] != "true": raise ValueError( "Unknown option in H2CH_encrypt_then_mac_ext: {0}".format( conf['H2CH_encrypt_then_mac_ext'])) else: ext[ExtensionType.encrypt_then_mac] = \ TLSExtension(extType=ExtensionType.encrypt_then_mac)\ .create(bytearray(0)) # server name if conf['H2CH_server_name'] == "no_ext": pass elif conf['H2CH_server_name'] == "correct": ext[ExtensionType.server_name] = \ SNIExtension().create(sni_hostname) elif conf['H2CH_server_name'] == "mismatch": ext[ExtensionType.server_name] = \ SNIExtension().create(sni_hostname + b'.www') else: raise ValueError("Unknown option in H2CH_server_name: {0}".format( conf['H2CH_server_name'])) # OCSP staple if conf['H2CH_status_request_ext'] == "false": pass elif conf['H2CH_status_request_ext'] != "true": raise ValueError( "Unknown option in H2CH_status_request_ext: {0}".format( conf['H2CH_status_request_ext'])) else: ext[ExtensionType.status_request] = \ StatusRequestExtension().create() # Extended Master Secret ext if conf['H2CH_extended_master_secret_ext'] == "false": pass elif conf['H2CH_extended_master_secret_ext'] != "true": raise ValueError( ("Unknown value in H2CH_extended_master_secret_ext" ": {0}").format(conf['H2CH_extended_master_secret_ext'])) else: ext[ExtensionType.extended_master_secret] = \ TLSExtension(extType=ExtensionType.extended_master_secret)\ .create(bytearray()) node = node.add_child( ClientHelloGenerator(suites, session_id=sess_ID, compression=compress, extensions=ext)) if conf['H2CH_server_name'] == "mismatch": node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.unrecognized_name)) al_node = node if conf['H2SH_SessionID'] == "resume": print("doing resumption") node = node.add_child(ExpectServerHello(resume=True)) if conf['H2CH_server_name'] == "mismatch": # make the sending of warning alert node optional al_node.next_sibling = node 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(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() else: node = node.add_child(ExpectServerHello()) if conf['H2CH_server_name'] == "mismatch": # make the sending of warning alert node optional al_node.next_sibling = node node = node.add_child(ExpectCertificate()) # TODO if conf['Certificate_Status_msg'] if conf['H2SKE_dh_group'] != "no_message": node = node.add_child(ExpectServerKeyExchange()) if conf['H2CR_sent'] == "true": node = node.add_child(ExpectCertificateRequest()) elif conf['H2CR_sent'] != "false": raise ValueError("Unknown option in H2CR_sent: {0}".format( conf['H2CR_sent'])) node = node.add_child(ExpectServerHelloDone()) if conf['H2CR_sent'] == "true": if conf['H2CV_signature_scheme'] == "no_message": node = node.add_child(CertificateGenerator()) else: node = node.add_child( CertificateGenerator(X509CertChain([cert]))) node = node.add_child(ClientKeyExchangeGenerator()) if conf['H2CV_signature_scheme'] != "no_message": sig = conf['H2CV_signature_scheme'] if "dsa" in sig: print("Changing {0} to RSA scheme in CV".format(sig)) sig = sig.replace("ecdsa", "rsa") sig = sig.replace("dsa", "rsa") sig = sig.replace("rsa_sha", "rsa_pkcs1_sha") sig = sig.replace("rsapss", "rsa_pss") if "sha224" in sig: scheme = (HashAlgorithm.sha224, SignatureAlgorithm.rsa) else: scheme = getattr(SignatureScheme, sig) node = node.add_child( CertificateVerifyGenerator(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( AlertGenerator(AlertLevel.warning, AlertDescription.close_notify)) node = node.add_child( ExpectAlert(AlertLevel.warning, AlertDescription.close_notify)) node.next_sibling = ExpectClose() return root