def __init__(self, connection_end="server", read_or_write="read", seq_num=0, compression_alg=Comp_NULL, ciphersuite=None, tls_version=0x0303): self.tls_version = tls_version # It is the user's responsibility to keep the record seq_num # under 2**64-1. If this value gets maxed out, the TLS class in # record.py will crash when trying to encode it with struct.pack(). self.seq_num = seq_num self.connection_end = connection_end self.row = read_or_write if ciphersuite is None: from scapy.layers.tls.crypto.suites import TLS_NULL_WITH_NULL_NULL ciphersuite = TLS_NULL_WITH_NULL_NULL self.ciphersuite = ciphersuite(tls_version=tls_version) if not self.ciphersuite.usable: warning( "TLS ciphersuite not usable. Is the cryptography Python module installed ?" ) # noqa: E501 return self.compression = compression_alg() self.key_exchange = ciphersuite.kx_alg() self.cipher = ciphersuite.cipher_alg() self.hash = ciphersuite.hash_alg() if tls_version > 0x0200: if ciphersuite.cipher_alg.type == "aead": self.hmac = None self.mac_len = self.cipher.tag_len else: self.hmac = ciphersuite.hmac_alg() self.mac_len = self.hmac.hmac_len else: self.hmac = ciphersuite.hmac_alg() # should be Hmac_NULL self.mac_len = self.hash.hash_len if tls_version >= 0x0304: self.hkdf = TLS13_HKDF(self.hash.name.lower()) else: self.prf = PRF(ciphersuite.hash_alg.name, tls_version)
def tls13_should_add_ClientHello(self): # we have to use the legacy, plaintext TLS record here supported_groups = ["secp256r1", "secp384r1"] if conf.crypto_valid_advanced: supported_groups.append("x25519") self.add_record(is_tls13=False) if self.client_hello: p = self.client_hello else: if self.ciphersuite is None: c = 0x1301 else: c = self.ciphersuite p = TLS13ClientHello(ciphers=c) ext = [] ext += TLS_Ext_SupportedVersion_CH(versions=["TLS 1.3"]) if self.cur_session.tls13_psk_secret: if self.tls13_psk_mode == "psk_dhe_ke": ext += TLS_Ext_PSKKeyExchangeModes(kxmodes="psk_dhe_ke") ext += TLS_Ext_SupportedGroups(groups=supported_groups) ext += TLS_Ext_KeyShare_CH( client_shares=[KeyShareEntry(group=self.curve)]) else: ext += TLS_Ext_PSKKeyExchangeModes(kxmodes="psk_ke") # RFC844, section 4.2.11. # "The "pre_shared_key" extension MUST be the last extension # in the ClientHello " hkdf = TLS13_HKDF("sha256") hash_len = hkdf.hash.digest_size psk_id = PSKIdentity(identity='Client_identity') # XXX see how to not pass binder as argument psk_binder_entry = PSKBinderEntry(binder_len=hash_len, binder=b"\x00" * hash_len) ext += TLS_Ext_PreSharedKey_CH(identities=[psk_id], binders=[psk_binder_entry]) else: ext += TLS_Ext_SupportedGroups(groups=supported_groups) ext += TLS_Ext_KeyShare_CH( client_shares=[KeyShareEntry(group=self.curve)]) ext += TLS_Ext_SignatureAlgorithms( sig_algs=["sha256+rsaepss", "sha256+rsa"]) p.ext = ext self.add_msg(p) raise self.TLS13_ADDED_CLIENTHELLO()
def tls13_should_add_ClientHello(self): # we have to use the legacy, plaintext TLS record here supported_groups = ["secp256r1", "secp384r1"] if conf.crypto_valid_advanced: supported_groups.append("x25519") self.add_record(is_tls13=False) if self.client_hello: p = self.client_hello else: if self.ciphersuite is None: c = 0x1301 else: c = self.ciphersuite p = TLS13ClientHello(ciphers=c) ext = [] ext += TLS_Ext_SupportedVersion_CH(versions=["TLS 1.3"]) s = self.cur_session if s.tls13_psk_secret: # Check if DHE is need (both for out of band and resumption PSK) if self.tls13_psk_mode == "psk_dhe_ke": ext += TLS_Ext_PSKKeyExchangeModes(kxmodes="psk_dhe_ke") ext += TLS_Ext_SupportedGroups(groups=supported_groups) ext += TLS_Ext_KeyShare_CH( client_shares=[KeyShareEntry(group=self.curve)]) else: ext += TLS_Ext_PSKKeyExchangeModes(kxmodes="psk_ke") # RFC844, section 4.2.11. # "The "pre_shared_key" extension MUST be the last extension # in the ClientHello " # Compute the pre_shared_key extension for resumption PSK if s.client_session_ticket: cs_cls = _tls_cipher_suites_cls[ s.tls13_ticket_ciphersuite] # noqa: E501 hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower()) hash_len = hkdf.hash.digest_size # We compute the client's view of the age of the ticket (ie # the time since the receipt of the ticket) in ms agems = int((time.time() - s.client_ticket_age) * 1000) # Then we compute the obfuscated version of the ticket age # by adding the "ticket_age_add" value included in the # ticket (modulo 2^32) obfuscated_age = ((agems + s.client_session_ticket_age_add) & 0xffffffff) psk_id = PSKIdentity(identity=s.client_session_ticket, obfuscated_ticket_age=obfuscated_age) psk_binder_entry = PSKBinderEntry(binder_len=hash_len, binder=b"\x00" * hash_len) ext += TLS_Ext_PreSharedKey_CH(identities=[psk_id], binders=[psk_binder_entry]) else: # Compute the pre_shared_key extension for out of band PSK # (SHA256 is used as default hash function for HKDF for out # of band PSK) hkdf = TLS13_HKDF("sha256") hash_len = hkdf.hash.digest_size psk_id = PSKIdentity(identity='Client_identity') # XXX see how to not pass binder as argument psk_binder_entry = PSKBinderEntry(binder_len=hash_len, binder=b"\x00" * hash_len) ext += TLS_Ext_PreSharedKey_CH(identities=[psk_id], binders=[psk_binder_entry]) else: ext += TLS_Ext_SupportedGroups(groups=supported_groups) ext += TLS_Ext_KeyShare_CH( client_shares=[KeyShareEntry(group=self.curve)]) ext += TLS_Ext_SignatureAlgorithms( sig_algs=["sha256+rsaepss", "sha256+rsa"]) p.ext = ext self.add_msg(p) raise self.TLS13_ADDED_CLIENTHELLO()
def INIT_TLS_SESSION(self): self.cur_session = tlsSession(connection_end="client") s = self.cur_session s.client_certs = self.mycert s.client_key = self.mykey v = self.advertised_tls_version if v: s.advertised_tls_version = v else: default_version = s.advertised_tls_version self.advertised_tls_version = default_version if s.advertised_tls_version >= 0x0304: # For out of band PSK, the PSK is given as an argument # to the automaton if self.tls13_psk_secret: s.tls13_psk_secret = binascii.unhexlify(self.tls13_psk_secret) # For resumed PSK, the PSK is computed from if self.session_ticket_file_in: with open(self.session_ticket_file_in, 'rb') as f: resumed_ciphersuite_len = struct.unpack("B", f.read(1))[0] s.tls13_ticket_ciphersuite = \ struct.unpack("!H", f.read(resumed_ciphersuite_len))[0] ticket_nonce_len = struct.unpack("B", f.read(1))[0] # XXX add client_session_nonce member in tlsSession s.client_session_nonce = f.read(ticket_nonce_len) client_ticket_age_len = struct.unpack("!H", f.read(2))[0] tmp = f.read(client_ticket_age_len) s.client_ticket_age = struct.unpack("!I", tmp)[0] client_ticket_age_add_len = struct.unpack("!H", f.read(2))[0] tmp = f.read(client_ticket_age_add_len) s.client_session_ticket_age_add = struct.unpack("!I", tmp)[0] ticket_len = struct.unpack("!H", f.read(2))[0] s.client_session_ticket = f.read(ticket_len) if self.resumption_master_secret: if s.tls13_ticket_ciphersuite not in _tls_cipher_suites_cls: # noqa: E501 warning("Unknown cipher suite %d" % s.tls13_ticket_ciphersuite) # noqa: E501 # we do not try to set a default nor stop the execution else: cs_cls = _tls_cipher_suites_cls[ s.tls13_ticket_ciphersuite] # noqa: E501 hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower()) hash_len = hkdf.hash.digest_size s.tls13_psk_secret = hkdf.expand_label( binascii.unhexlify( self.resumption_master_secret), # noqa: E501 b"resumption", s.client_session_nonce, # noqa: E501 hash_len) raise self.CONNECT()
def tls13_should_add_ClientHello_Retry(self): s = self.cur_session s.tls13_retry = True # we have to use the legacy, plaintext TLS record here self.add_record(is_tls13=False) # We retrieve the group to be used and the selected version from the # previous message hrr = s.handshake_messages_parsed[-1] if isinstance(hrr, TLS13HelloRetryRequest): pass ciphersuite = hrr.cipher if hrr.ext: for e in hrr.ext: if isinstance(e, TLS_Ext_KeyShare_HRR): selected_group = e.selected_group if isinstance(e, TLS_Ext_SupportedVersion_SH): selected_version = e.version if not selected_group or not selected_version: raise self.CLOSE_NOTIFY() ext = [] ext += TLS_Ext_SupportedVersion_CH( versions=[_tls_version[selected_version]]) # noqa: E501 if s.tls13_psk_secret: if self.tls13_psk_mode == "psk_dhe_ke": ext += TLS_Ext_PSKKeyExchangeModes(kxmodes="psk_dhe_ke"), ext += TLS_Ext_SupportedGroups( groups=[_tls_named_groups[selected_group]]) # noqa: E501 ext += TLS_Ext_KeyShare_CH(client_shares=[ KeyShareEntry(group=selected_group) ]) # noqa: E501 else: ext += TLS_Ext_PSKKeyExchangeModes(kxmodes="psk_ke") if s.client_session_ticket: # XXX Retrieve parameters from first ClientHello... cs_cls = _tls_cipher_suites_cls[s.tls13_ticket_ciphersuite] hkdf = TLS13_HKDF(cs_cls.hash_alg.name.lower()) hash_len = hkdf.hash.digest_size # We compute the client's view of the age of the ticket (ie # the time since the receipt of the ticket) in ms agems = int((time.time() - s.client_ticket_age) * 1000) # Then we compute the obfuscated version of the ticket age by # adding the "ticket_age_add" value included in the ticket # (modulo 2^32) obfuscated_age = ((agems + s.client_session_ticket_age_add) & 0xffffffff) psk_id = PSKIdentity(identity=s.client_session_ticket, obfuscated_ticket_age=obfuscated_age) psk_binder_entry = PSKBinderEntry(binder_len=hash_len, binder=b"\x00" * hash_len) ext += TLS_Ext_PreSharedKey_CH(identities=[psk_id], binders=[psk_binder_entry]) else: hkdf = TLS13_HKDF("sha256") hash_len = hkdf.hash.digest_size psk_id = PSKIdentity(identity='Client_identity') psk_binder_entry = PSKBinderEntry(binder_len=hash_len, binder=b"\x00" * hash_len) ext += TLS_Ext_PreSharedKey_CH(identities=[psk_id], binders=[psk_binder_entry]) else: ext += TLS_Ext_SupportedGroups( groups=[_tls_named_groups[selected_group]]) # noqa: E501 ext += TLS_Ext_KeyShare_CH(client_shares=[ KeyShareEntry(group=selected_group) ]) # noqa: E501 ext += TLS_Ext_SignatureAlgorithms(sig_algs=["sha256+rsaepss"]) p = TLS13ClientHello(ciphers=ciphersuite, ext=ext) self.add_msg(p) raise self.TLS13_ADDED_CLIENTHELLO()