##############################
% IPSec layer regression tests
##############################

###############################################################################
+ IPv4 / ESP - Transport - Encryption Algorithms

#######################################
= IPv4 / ESP - Transport - NULL - NULL

import socket

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - DES - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='DES', crypt_key='8bytekey',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an ESP layer
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - 3DES - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='3DES', crypt_key='threedifferent8byteskeys',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an ESP layer
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable 
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - AES-CBC - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - AES-CTR - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CTR', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - Blowfish - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='Blowfish', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - CAST - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='CAST', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

###############################################################################
+ IPv4 / ESP - Tunnel - Encryption Algorithms

#######################################
= IPv4 / ESP - Tunnel - NULL - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - DES - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='DES', crypt_key='8bytekey',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
* the encrypted packet should have an ESP layer
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - 3DES - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='3DES', crypt_key='threedifferent8byteskeys',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
* the encrypted packet should have an ESP layer
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - AES-CBC - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - AES-CTR - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CTR', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - Blowfish - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='Blowfish', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - CAST - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='CAST', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

###############################################################################
+ IPv4 / ESP - Transport - Authentication Algorithms

#######################################
= IPv4 / ESP - Transport - NULL - HMAC-SHA1-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - NULL - HMAC-SHA1-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Transport - NULL - SHA2-256-128

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-256-128', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Transport - NULL - SHA2-256-128 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-256-128', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Transport - NULL - SHA2-384-192

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-384-192', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Transport - NULL - SHA2-384-192 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-384-192', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Transport - NULL - SHA2-512-256

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-512-256', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Transport - NULL - SHA2-512-256 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-512-256', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Transport - NULL - HMAC-MD5-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-MD5-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Transport - NULL - HMAC-MD5-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-MD5-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Transport - NULL - AES-CMAC-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Transport - NULL - AES-CMAC-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

###############################################################################
+ IPv4 / ESP - Tunnel - Authentication Algorithms

#######################################
= IPv4 / ESP - Tunnel - NULL - HMAC-SHA1-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - NULL - HMAC-SHA1-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Tunnel - NULL - SHA2-256-128

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-256-128', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Tunnel - NULL - SHA2-256-128 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-256-128', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Tunnel - NULL - SHA2-384-192

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-384-192', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Tunnel - NULL - SHA2-384-192 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-384-192', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Tunnel - NULL - SHA2-512-256

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-512-256', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Tunnel - NULL - SHA2-512-256 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='SHA2-512-256', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Tunnel - NULL - HMAC-MD5-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-MD5-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Tunnel - NULL - HMAC-MD5-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-MD5-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Tunnel - NULL - AES-CMAC-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet should be preserved
assert(d == p)

#######################################
= IPv4 / ESP - Tunnel - NULL - AES-CMAC-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should be readable
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

###############################################################################
+ IPv4 / ESP - Encryption + Authentication

#######################################
= IPv4 / ESP - Transport - AES-CBC - HMAC-SHA1-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - AES-CBC - HMAC-SHA1-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Transport - AES-GCM - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Transport - AES-GCM - NULL - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err
#######################################
= IPv4 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / ESP - Tunnel - AES-GCM - NULL

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption original packet should be preserved
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / ESP - Tunnel - AES-GCM - NULL - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

###############################################################################
+ IPv4 / AH - Transport

#######################################
= IPv4 / AH - Transport - HMAC-SHA1-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='sixteenbytes key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / AH - Transport - HMAC-SHA1-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='sixteenbytes key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before decryption
e[TCP].sport = 5

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Transport - SHA2-256-128

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-256-128', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / AH - Transport - SHA2-256-128 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-256-128', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e[TCP].dport = 46

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Transport - SHA2-384-192

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-384-192', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / AH - Transport - SHA2-384-192 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-384-192', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e[TCP].dport = 46

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Transport - SHA2-512-256

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-512-256', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / AH - Transport - SHA2-512-256 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-512-256', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e[TCP].dport = 46

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Transport - HMAC-MD5-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-MD5-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / AH - Transport - HMAC-MD5-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-MD5-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e[TCP].dport = 46

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Transport - AES-CMAC-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / AH - Transport - AES-CMAC-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key')

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '1.1.1.1' and e.dst == '2.2.2.2')
assert(e.chksum != p.chksum)
* the encrypted packet should have an AH layer
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e[TCP].dport = 46

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

###############################################################################
+ IPv4 / AH - Tunnel

#######################################
= IPv4 / AH - Tunnel - HMAC-SHA1-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv4 / AH - Tunnel - HMAC-SHA1-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e.dst = '4.4.4.4'

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Tunnel - SHA2-256-128

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-256-128', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d == p)

#######################################
= IPv4 / AH - Tunnel - SHA2-256-128 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-256-128', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e.dst = '4.4.4.4'

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Tunnel - SHA2-384-192

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-384-192', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d == p)

#######################################
= IPv4 / AH - Tunnel - SHA2-384-192 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-384-192', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e.dst = '4.4.4.4'

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Tunnel - SHA2-512-256

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-512-256', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d == p)

#######################################
= IPv4 / AH - Tunnel - SHA2-512-256 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='SHA2-512-256', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e.dst = '4.4.4.4'

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Tunnel - HMAC-MD5-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-MD5-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d == p)

#######################################
= IPv4 / AH - Tunnel - HMAC-MD5-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-MD5-96', auth_key='secret key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e.dst = '4.4.4.4'

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv4 / AH - Tunnel - AES-CMAC-96

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.ttl = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d == p)

#######################################
= IPv4 / AH - Tunnel - AES-CMAC-96 - altered packet

p = IP(src='1.1.1.1', dst='2.2.2.2')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IP(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='AES-CMAC-96', auth_key='sixteenbytes key',
                         tunnel_header=IP(src='11.11.11.11', dst='22.22.22.22'))

e = sa.encrypt(p)
e

assert(isinstance(e, IP))
assert(e.src == '11.11.11.11' and e.dst == '22.22.22.22')
assert(e.chksum != p.chksum)
assert(e.proto == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e.dst = '4.4.4.4'

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

###############################################################################
+ IPv6 / ESP

#######################################
= IPv6 / ESP - Transport - NULL - NULL

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Transport - AES-CBC - NULL

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Transport - NULL - HMAC-SHA1-96

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Transport - NULL - HMAC-SHA1-96 - altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data =e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv6 / ESP - Transport - AES-CBC - HMAC-SHA1-96

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Transport - AES-CBC - HMAC-SHA1-96 - altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv6 / ESP - Transport - AES-GCM - NULL

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet should be preserved
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Transport - AES-GCM - NULL - altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None)

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv6 / ESP - Tunnel - NULL - NULL

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Tunnel - AES-CBC - NULL

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Tunnel - NULL - HMAC-SHA1-96

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* integrity verification should pass
d = sa.decrypt(e)

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Tunnel - NULL - HMAC-SHA1-96 - altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='NULL', crypt_key=None,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
assert(b'testdata' in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].data = e[ESP].data.replace(b'\x01', b'\x21')

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv6 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / ESP - Tunnel - AES-CBC - HMAC-SHA1-96 altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-CBC', crypt_key='sixteenbytes key',
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IPv6(src = 'aa::bb', dst = 'bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv6 / ESP - Tunnel - AES-GCM - NULL

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

d = sa.decrypt(e)
d

* after decryption the original packet should be unaltered
assert(d == p)

#######################################
= IPv6 / ESP - Tunnel - AES-GCM - NULL - altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(ESP, spi=0x222,
                         crypt_algo='AES-GCM', crypt_key='16bytekey+4bytenonce',
                         auth_algo='NULL', auth_key=None,
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_ESP)
assert(e.haslayer(ESP))
assert(not e.haslayer(TCP))
assert(e[ESP].spi == sa.spi)
* after encryption the original packet payload should NOT be readable
assert(b'testdata' not in e[ESP].data)

* simulate the alteration of the packet before decryption
e[ESP].seq += 1

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

###############################################################################
+ IPv6 / AH

#######################################
= IPv6 / AH - Transport - HMAC-SHA1-96

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
* the encrypted packet should have an AH layer
assert(e.nh == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.hlim = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d[TCP] == p[TCP])

#######################################
= IPv6 / AH - Transport - HMAC-SHA1-96 - altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
assert(e.src == '11::22' and e.dst == '22::11')
* the encrypted packet should have an AH layer
assert(e.nh == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e[TCP].dport = 46

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

#######################################
= IPv6 / AH - Tunnel - HMAC-SHA1-96

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* alter mutable fields in the packet
e.hlim = 2

* integrity verification should pass
d = sa.decrypt(e)
d

* after decryption the original packet payload should be unaltered
assert(d == p)

#######################################
= IPv6 / AH - Tunnel - HMAC-SHA1-96 - altered packet

p = IPv6(src='11::22', dst='22::11')
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key',
                         tunnel_header=IPv6(src='aa::bb', dst='bb::aa'))

e = sa.encrypt(p)
e

assert(isinstance(e, IPv6))
* after encryption packet should be encapsulated with the given ip tunnel header
assert(e.src == 'aa::bb' and e.dst == 'bb::aa')
assert(e.nh == socket.IPPROTO_AH)
assert(e.haslayer(AH))
assert(e.haslayer(TCP))
assert(e[AH].spi == sa.spi)

* simulate the alteration of the packet before verification
e.src = 'cc::ee'

* integrity verification should fail
try:
    d = sa.decrypt(e)
    assert(False)
except IPSecIntegrityError as err:
    err

###############################################################################
+ IPv6 + Extensions / AH

#######################################
= IPv6 + Extensions / AH - Transport

p = IPv6(src='11::22', dst='22::11')
p /= IPv6ExtHdrHopByHop()
p /= IPv6ExtHdrDestOpt()
p /= IPv6ExtHdrRouting()
p /= IPv6ExtHdrDestOpt()
p /= IPv6ExtHdrFragment()
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(e.src == '11::22' and e.dst == '22::11')
* AH header should be inserted between the routing header and the dest options header
assert(isinstance(e[AH].underlayer, IPv6ExtHdrRouting))
assert(isinstance(e[AH].payload, IPv6ExtHdrDestOpt))

#######################################
= IPv6 + Routing Header / AH - Transport

p = IPv6(src='11::22', dst='22::11')
p /= IPv6ExtHdrHopByHop()
p /= IPv6ExtHdrRouting(addresses=['aa::bb', 'cc::dd', 'ee::ff'])
p /= TCP(sport=45012, dport=80)
p /= Raw(b'testdata')
p = IPv6(bytes(p))
p

sa = SecurityAssociation(AH, spi=0x222,
                         auth_algo='HMAC-SHA1-96', auth_key='secret key')

e = sa.encrypt(p)
e

assert(e.src == '11::22' and e.dst == '22::11')
* AH header should be inserted between the routing header and TCP
assert(isinstance(e[AH].underlayer, IPv6ExtHdrRouting))
assert(isinstance(e[AH].payload, TCP))

* reorder the routing header as the receiver will get it
final = e[IPv6ExtHdrRouting].addresses.pop()
e[IPv6ExtHdrRouting].addresses.insert(0, e.dst)
e.dst = final
e[IPv6ExtHdrRouting].segleft = 0

* integrity verification should pass
d = sa.decrypt(e)
d

###############################################################################
+ IKEv2

#######################################
= IKEv2

from kamene.contrib.ikev2 import *

p = UDP(bytes(UDP()/IKEv2()))
p

assert(p.sport == 500)
assert(p.dport == 500)

#######################################
= IKEv2 - next_payload

assert(IKEv2(bytes(IKEv2()/IKEv2_payload_Transform())).next_payload == 3)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_SA()       )).next_payload == 33)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_KE()       )).next_payload == 34)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_IDi()      )).next_payload == 35)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_IDr()      )).next_payload == 36)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_CERT()     )).next_payload == 37)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_CERTREQ()  )).next_payload == 38)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_Nonce()    )).next_payload == 40)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_Notify()   )).next_payload == 41)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_Delete()   )).next_payload == 42)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_VendorID() )).next_payload == 43)
assert(IKEv2(bytes(IKEv2()/IKEv2_payload_Encrypted())).next_payload == 46)

#######################################
= IKEv2_payload_Transform

p = IKEv2_payload_Transform(bytes(IKEv2_payload_Transform()))
p

assert(p.next_payload == 0)
assert(p.res == 0)
assert(p.length == 8)
assert(p.transform_type == 0)
assert(p.res2 == 0)
assert(p.transform_id == 0)
assert(p.key_length == 0)
assert(bytes(p) == b'\x00\x00\x00\x08\x00\x00\x00\x00')

p.length=12
assert(bytes(p) == b'\x00\x00\x00\x0c\x00\x00\x00\x00\x80\x0e\x00\x00')

#######################################
= IKEv2_payload_KE

p = IKEv2_payload_KE(bytes(IKEv2_payload_KE()))
p

assert(p.next_payload == 0)
assert(p.res == 0)
assert(p.length == 8)
assert(p.group == 0)
assert(p.res2 == 0)
assert(p.load == b'')
assert(bytes(p) == b'\x00\x00\x00\x08\x00\x00\x00\x00')

#######################################
= IKEv2_payload_Notify - Default

p = IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()))
p

assert(p.next_payload == 0)
assert(p.res == 0)
assert(p.length == 8)
assert(p.proto == 0)
assert(p.SPIsize == 0)
assert(p.type == 0)
assert(p.load == b'')
assert(bytes(p) == b'\x00\x00\x00\x08\x00\x00\x00\x00')

#######################################
= IKEv2_payload_Notify - Message Types

assert(IKEv2_payload_Notify(type = 'INVALID_IKE_SPI').type == 4)
assert(IKEv2_payload_Notify(type = 'FAILED_CP_REQUIRED').type == 37)
assert(IKEv2_payload_Notify(type = 'NAT_DETECTION_SOURCE_IP').type == 16388)
assert(IKEv2_payload_Notify(type = 'NAT_DETECTION_DESTINATION_IP').type == 16389)

#######################################
= IKEv2_payload_Notify - Set next_payload on previous payload

assert(IKEv2_payload_Transform(bytes(IKEv2_payload_Transform()/IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_SA       (bytes(IKEv2_payload_SA()       /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_KE       (bytes(IKEv2_payload_KE()       /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_IDi      (bytes(IKEv2_payload_IDi()      /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_IDr      (bytes(IKEv2_payload_IDr()      /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_CERT     (bytes(IKEv2_payload_CERT()     /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_CERTREQ  (bytes(IKEv2_payload_CERTREQ()  /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_Nonce    (bytes(IKEv2_payload_Nonce()    /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_Notify   (bytes(IKEv2_payload_Notify()   /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_Delete   (bytes(IKEv2_payload_Delete()   /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_VendorID (bytes(IKEv2_payload_VendorID() /IKEv2_payload_Notify())).next_payload == 41)
assert(IKEv2_payload_Encrypted(bytes(IKEv2_payload_Encrypted()/IKEv2_payload_Notify())).next_payload == 41)

#######################################
= IKEv2_payload_Notify - Set next_payload for next payload

assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_Transform())).next_payload == 3)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_SA()       )).next_payload == 33)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_KE()       )).next_payload == 34)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_IDi()      )).next_payload == 35)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_IDr()      )).next_payload == 36)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_CERT()     )).next_payload == 37)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_CERTREQ()  )).next_payload == 38)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_Nonce()    )).next_payload == 40)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_Notify()   )).next_payload == 41)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_Delete()   )).next_payload == 42)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_VendorID() )).next_payload == 43)
assert(IKEv2_payload_Notify(bytes(IKEv2_payload_Notify()/IKEv2_payload_Encrypted())).next_payload == 46)

######################################
= IKEv2_payload_CERT - Certificate Encodings

assert(IKEv2_payload_CERT(cert_type = 'X.509 Certificate - Signature').cert_type == 4)
assert(IKEv2_payload_CERT(cert_type = 'Hash and URL of X.509 certificate').cert_type == 12)

######################################
= IKEv2_payload_CERT - Default

p = IKEv2_payload_CERT(bytes(IKEv2_payload_CERT()))
p

assert(p.next_payload == 0)
assert(p.res == 0)
assert(p.length == 5)
assert(p.cert_type == 0)
assert(p.cert_data == b'')
assert(bytes(p) == b'\x00\x00\x00\x05\x00')

######################################
= IKEv2_payload_CERTREQ - Default

p = IKEv2_payload_CERTREQ(bytes(IKEv2_payload_CERTREQ()))
p

assert(p.next_payload == 0)
assert(p.res == 0)
assert(p.length == 5)
assert(p.cert_type == 0)
assert(p.cert_data == b'')
assert(bytes(p) == b'\x00\x00\x00\x05\x00')
