TLS session handler.

class scapy.layers.tls.session.connState(connection_end='server', read_or_write='read', seq_num=0, compression_alg=<class 'scapy.layers.tls.crypto.compression.Comp_NULL'>, ciphersuite=None, tls_version=771)

Bases: object

From RFC 5246, section 6.1: A TLS connection state is the operating environment of the TLS Record Protocol. It specifies a compression algorithm, an encryption algorithm, and a MAC algorithm. In addition, the parameters for these algorithms are known: the MAC key and the bulk encryption keys for the connection in both the read and the write directions. Logically, there are always four connection states outstanding: the current read and write states, and the pending read and write states. All records are processed under the current read and write states. The security parameters for the pending states can be set by the TLS Handshake Protocol, and the ChangeCipherSpec can selectively make either of the pending states current, in which case the appropriate current state is disposed of and replaced with the pending state; the pending state is then reinitialized to an empty state. It is illegal to make a state that has not been initialized with security parameters a current state. The initial current state always specifies that no encryption, compression, or MAC will be used.

(For practical reasons, Scapy scraps these two last lines, through the implementation of dummy ciphers and MAC with TLS_NULL_WITH_NULL_NULL.)

These attributes and behaviours are mostly mapped in this class. Also, note that Scapy may make a current state out of a pending state which has been initialized with dummy security parameters. We need this in order to know when the content of a TLS message is encrypted, whether we possess the right keys to decipher/verify it or not. For instance, when Scapy parses a CKE without knowledge of any secret, and then a CCS, it needs to know that the following Finished is encrypted and signed according to a new cipher suite, even though it cannot decipher the message nor verify its integrity.

debug_repr(name, secret)
derive_keys(client_random=b'', server_random=b'', master_secret=b'')

This is used mostly as a way to keep the cipher state and the seq_num.


There is actually only one key, the CLIENT-READ-KEY or -WRITE-KEY.

Note that skip_first is opposite from the one with SSLv3 derivation.

Also, if needed, the IV should be set elsewhere.

class scapy.layers.tls.session.readConnState(**kargs)

Bases: scapy.layers.tls.session.connState

class scapy.layers.tls.session.tlsSession(ipsrc=None, ipdst=None, sport=None, dport=None, sid=None, connection_end='server', wcs=None, rcs=None)

Bases: object

This is our TLS context, which gathers information from both sides of the TLS connection. These sides are represented by a readConnState instance and a writeConnState instance. Along with overarching network attributes, a tlsSession object also holds negotiated, shared information, such as the key exchange parameters and the master secret (when available).

The default connection_end is “server”. This corresponds to the expected behaviour for static exchange analysis (with a ClientHello parsed first).


This function computes the Early Secret, the binder_key, the client_early_traffic_secret and the early_exporter_master_secret (See RFC8446, section 7.1).

The parameter external is used for the computation of the binder_key:

  • For external PSK provisioned outside out of TLS, the parameter external must be True.

  • For resumption PSK, the parameter external must be False.

If no argument is specified, the label “res binder” will be used by default.

Ciphers key and IV are updated accordingly for 0-RTT data. self.handshake_messages should be ClientHello only.


Ciphers key and IV are updated accordingly for Handshake data. self.handshake_messages should be ClientHello…ServerHello.

compute_tls13_next_traffic_secrets(connection_end, read_or_write)

Ciphers key and IV are updated accordingly.


self.handshake_messages should be ClientHello…ClientFinished.


Ciphers key and IV are updated accordingly for Application data. self.handshake_messages should be ClientHello…ServerFinished.

compute_tls13_verify_data(connection_end, read_or_write)

This function takes a tlsSession object and swaps the IP addresses, ports, connection ends and connection states. The triggered_commit are also swapped (though it is probably overkill, it is cleaner this way).

It is useful for static analysis of a series of messages from both the client and the server. In such a situation, it should be used every time the message being read comes from a different side than the one read right before, as the reading state becomes the writing state, and vice versa. For instance you could do:

client_hello = open(‘client_hello.raw’).read() <read other messages>

m1 = TLS(client_hello) m2 = TLS(server_hello, tls_session=m1.tls_session.mirror()) m3 = TLS(server_cert, tls_session=m2.tls_session) m4 = TLS(client_keyexchange, tls_session=m3.tls_session.mirror())

use_explicit_iv(version, cipher_type)
class scapy.layers.tls.session.writeConnState(**kargs)

Bases: scapy.layers.tls.session.connState