scapy.layers.tls.record
Common TLS fields & bindings.
This module covers the record layer, along with the ChangeCipherSpec, Alert and ApplicationData submessages. For the Handshake type, see tls_handshake.py.
See the TLS class documentation for more information.
- class scapy.layers.tls.record.TLS(_pkt, /, *, type=None, version=None, len=None, iv=None, msg=[], mac=None, pad=None, padlen=None)[source]
Bases:
_GenericTLSSessionInheritance
The generic TLS Record message, based on section 6.2 of RFC 5246.
When reading a TLS message, we try to parse as much as we can. In .pre_dissect(), according to the type of the current cipher algorithm (self.tls_session.rcs.cipher.type), we extract the ‘iv’, ‘mac’, ‘pad’ and ‘padlen’. Some of these fields may remain blank: for instance, when using a stream cipher, there is no IV nor any padding. The ‘len’ should always hold the length of the ciphered message; for the plaintext version, you should rely on the additional ‘deciphered_len’ attribute.
XXX Fix ‘deciphered_len’ which should not be defined when failing with AEAD decryption. This is related to the ‘decryption_success’ below. Also, follow this behaviour in record_sslv2.py and record_tls13.py
Once we have isolated the ciphered message aggregate (which should be one or several TLS messages of the same type), we try to decipher it. Either we succeed and store the clear data in ‘msg’, or we graciously fail with a CipherError and store the ciphered data in ‘msg’.
Unless the user manually provides the session secrets through the passing of a ‘tls_session’, obviously the ciphered messages will not be deciphered. Indeed, the need for a proper context may also present itself when trying to parse clear handshake messages.
For instance, suppose you sniffed the beginning of a DHE-RSA negotiation:
t1 = TLS(<client_hello>) t2 = TLS(<server_hello | certificate | server_key_exchange>) t3 = TLS(<server_hello | certificate | server_key_exchange>, tls_session=t1.tls_session)
(Note that to do things properly, here ‘t1.tls_session’ should actually be ‘t1.tls_session.mirror()’. See session.py for explanations.)
As no context was passed to t2, neither was any client_random. Hence Scapy will not be able to verify the signature of the server_key_exchange inside t2. However, it should be able to do so for t3, thanks to the tls_session. The consequence of not having a complete TLS context is even more obvious when trying to parse ciphered content, as we described before.
Thus, in order to parse TLS-protected communications with Scapy: _either Scapy reads every message from one side of the TLS connection and builds every message from the other side (as such, it should know the secrets needed for the generation of the pre_master_secret), while passing the same tls_session context (this is how our automaton.py mostly works); _or, if Scapy did not build any TLS message, it has to create a TLS context and feed it with secrets retrieved by whatever technique. Note that the knowing the private key of the server certificate will not be sufficient if a PFS ciphersuite was used. However, if you got a master_secret somehow, use it with tls_session.(w|r)cs.derive_keys() and leave the rest to Scapy.
When building a TLS message with raw_stateful, we expect the tls_session to have the right parameters for ciphering. Else, .post_build() might fail.
- aliastypes
- deciphered_len
- classmethod dispatch_hook(_pkt=None, *args, **kargs)[source]
If the TLS class was called on raw SSLv2 data, we want to return an SSLv2 record instance. We acknowledge the risk of SSLv2 packets with a msglen of 0x1403, 0x1503, 0x1603 or 0x1703 which will never be casted as SSLv2 records but TLS ones instead, but hey, we can’t be held responsible for low-minded extensibility choices.
- do_dissect_payload(s)[source]
Try to dissect the following data as a TLS message. Note that overloading .guess_payload_class() would not be enough, as the TLS session to be used would get lost.
- fields_desc
Display RFC-like schema
0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | TYPE | VERSION | LEN | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | IV | MSG | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | MAC | PAD | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | PADLEN | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ Fig. TLS
TLS fields type
None
version
_TLSVersionField
None
len
_TLSLengthField
None
iv
_TLSIVField
None
msg
_TLSMsgListField
[]
mac
_TLSMACField
None
pad
_TLSPadField
None
padlen
_TLSPadLenField
None
- class scapy.layers.tls.record.TLSAlert(_pkt, /, *, level=None, descr=None)[source]
Bases:
_GenericTLSSessionInheritance
- aliastypes
- class scapy.layers.tls.record.TLSApplicationData(_pkt, /, *, data=b'')[source]
Bases:
_GenericTLSSessionInheritance
- aliastypes
- class scapy.layers.tls.record.TLSChangeCipherSpec(_pkt, /, *, msgtype=1)[source]
Bases:
_GenericTLSSessionInheritance
Note that, as they are not handshake messages, the ccs messages do not get appended to the list of messages whose integrity gets verified through the Finished messages.
- aliastypes