scapy.layers.ipsec module

IPsec layer

Example of use:

>>> sa = SecurityAssociation(ESP, spi=0xdeadbeef, crypt_algo='AES-CBC',
...                          crypt_key='sixteenbytes key')
>>> p = IP(src='1.1.1.1', dst='2.2.2.2')
>>> p /= TCP(sport=45012, dport=80)
>>> p /= Raw('testdata')
>>> p = IP(raw(p))
>>> p
<IP  version=4L ihl=5L tos=0x0 len=48 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x74c2 src=1.1.1.1 dst=2.2.2.2 options=[] |<TCP  sport=45012 dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x1914 urgptr=0 options=[] |<Raw  load='testdata' |>>>  # noqa: E501
>>>
>>> e = sa.encrypt(p)
>>> e
<IP  version=4L ihl=5L tos=0x0 len=76 id=1 flags= frag=0L ttl=64 proto=esp chksum=0x747a src=1.1.1.1 dst=2.2.2.2 |<ESP  spi=0xdeadbeef seq=1 data=b'øÛ
ƒ[T«\ÒíÑåÈYÂ¥d’Á¦’ƒ1æÁ]šÖK}W‹Ffd¥B*+Þȉ¿{©' |>>  # noqa: E501
>>>
>>> d = sa.decrypt(e)
>>> d
<IP  version=4L ihl=5L tos=0x0 len=48 id=1 flags= frag=0L ttl=64 proto=tcp chksum=0x74c2 src=1.1.1.1 dst=2.2.2.2 |<TCP  sport=45012 dport=http seq=0 ack=0 dataofs=5L reserved=0L flags=S window=8192 chksum=0x1914 urgptr=0 options=[] |<Raw  load='testdata' |>>>  # noqa: E501
>>>
>>> d == p
True
class scapy.layers.ipsec.AH

Bases: scapy.packet.Packet

Authentication Header

See https://tools.ietf.org/rfc/rfc4302.txt

aliastypes = [<class 'scapy.layers.ipsec.AH'>, <class 'scapy.packet.Packet'>]
fields_desc = [<Field (AH).nh>, <Field (AH).payloadlen>, <Field (AH).reserved>, <Field (AH).spi>, <Field (AH).seq>, <Field (AH).icv>, <Field (AH).padding>]
payload_guess = [({'nh': 0}, <class 'scapy.layers.inet.IP'>), ({'nh': 41}, <class 'scapy.layers.inet6.IPv6'>)]
class scapy.layers.ipsec.AuthAlgo(name, mac, digestmod, icv_size, key_size=None)

Bases: object

IPsec integrity algorithm

check_key(key)

Check that the key length is valid.

Parameters:key – a byte string
new_mac(**kwargs)
sign(pkt, key)

Sign an IPsec (ESP or AH) packet with this algo.

Parameters:
  • pkt – a packet that contains a valid encrypted ESP or AH layer
  • key – the authentication key, a byte string
Returns:

the signed packet

verify(pkt, key)

Check that the integrity check value (icv) of a packet is valid.

Parameters:
  • pkt – a packet that contains a valid encrypted ESP or AH layer
  • key – the authentication key, a byte string
Raises:

scapy.layers.ipsec.IPSecIntegrityError – if the integrity check fails

class scapy.layers.ipsec.CryptAlgo(name, cipher, mode, block_size=None, iv_size=None, key_size=None, icv_size=None, salt_size=None, format_mode_iv=None)

Bases: object

IPsec encryption algorithm

check_key(key)

Check that the key length is valid.

Parameters:key – a byte string
decrypt(sa, esp, key, icv_size=None, esn_en=False, esn=0)

Decrypt an ESP packet

Parameters:
  • sa – the SecurityAssociation associated with the ESP packet.
  • esp – an encrypted ESP packet
  • key – the secret key used for encryption
  • icv_size – the length of the icv used for integrity check
  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm
  • esn – extended sequence number (32 MSB)
Returns:

a valid ESP packet encrypted with this algorithm

Raises:

scapy.layers.ipsec.IPSecIntegrityError – if the integrity check fails with an AEAD algorithm

encrypt(sa, esp, key, esn_en=False, esn=0)

Encrypt an ESP packet

Parameters:
  • sa – the SecurityAssociation associated with the ESP packet.
  • esp – an unencrypted _ESPPlain packet with valid padding
  • key – the secret key used for encryption
Esn_en:

extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm

Esn:

extended sequence number (32 MSB)

Returns:

a valid ESP packet encrypted with this algorithm

generate_iv()

Generate a random initialization vector.

new_cipher(**kwargs)
pad(esp)

Add the correct amount of padding so that the data to encrypt is exactly a multiple of the algorithm’s block size.

Also, make sure that the total ESP packet length is a multiple of 4 bytes.

Parameters:esp – an unencrypted _ESPPlain packet
Returns:an unencrypted _ESPPlain packet with valid padding
class scapy.layers.ipsec.ESP

Bases: scapy.packet.Packet

Encapsulated Security Payload

See https://tools.ietf.org/rfc/rfc4303.txt

aliastypes = [<class 'scapy.layers.ipsec.ESP'>, <class 'scapy.packet.Packet'>]
fields_desc = [<Field (ESP).spi>, <Field (ESP).seq>, <Field (ESP).data>]
exception scapy.layers.ipsec.IPSecIntegrityError

Bases: Exception

Error risen when the integrity check fails.

class scapy.layers.ipsec.SecurityAssociation(proto, spi, seq_num=1, crypt_algo=None, crypt_key=None, auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None, esn_en=False, esn=0)

Bases: object

This class is responsible of “encryption” and “decryption” of IPsec packets. # noqa: E501

SUPPORTED_PROTOS = (<class 'scapy.layers.inet.IP'>, <class 'scapy.layers.inet6.IPv6'>)
check_spi(pkt)
decrypt(pkt, verify=True, esn_en=None, esn=None)

Decrypt (and decapsulate) an IP(v6) packet containing ESP or AH.

Parameters:
  • pkt – the packet to decrypt
  • verify – if False, do not perform the integrity check
  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm
  • esn – extended sequence number (32 MSB)
Returns:

the decrypted/decapsulated packet

Raises:

scapy.layers.ipsec.IPSecIntegrityError – if the integrity check fails

encrypt(pkt, seq_num=None, iv=None, esn_en=None, esn=None)

Encrypt (and encapsulate) an IP(v6) packet with ESP or AH according to this SecurityAssociation.

Parameters:
  • pkt – the packet to encrypt
  • seq_num – if specified, use this sequence number instead of the generated one
  • esn_en – extended sequence number enable which allows to use 64-bit sequence number instead of 32-bit when using an AEAD algorithm
  • esn – extended sequence number (32 MSB)
  • iv – if specified, use this initialization vector for encryption instead of a random one.
Returns:

the encrypted/encapsulated packet

scapy.layers.ipsec.split_for_transport(orig_pkt, transport_proto)

Split an IP(v6) packet in the correct location to insert an ESP or AH header.

Parameters:
  • orig_pkt – the packet to split. Must be an IP or IPv6 packet
  • transport_proto – the IPsec protocol number that will be inserted at the split position.
Returns:

a tuple (header, nh, payload) where nh is the protocol number of payload.

scapy.layers.ipsec.zero_mutable_fields(pkt, sending=False)

When using AH, all “mutable” fields must be “zeroed” before calculating the ICV. See RFC 4302, Section 3.3.3.1. Handling Mutable Fields.

Parameters:
  • pkt – an IP(v6) packet containing an AH layer. NOTE: The packet will be modified
  • sending – if true, ipv6 routing headers will not be reordered