encryptionopensslipsec

Need help in decrypting ESP payload and form a new packet


I am trying to build an application which implements IPSec functionality. The application receives an encrypted packet, it then decrypts the encrypted packet and sends out decrypted packet to other application.

I have sent an encrypted packet using scapy (AES-CBC mode with 128 key). When application receives this packet, it needs to decrypt the ESP payload (other headers are already dealt-with).

Encrypted ESP Payload (In hexadecimal format): df 2d 42 15 29 ca 6c 77 9d 60 03 ef 4f 1d fa a9 44 85 39 80 b3 e1 9d d1 e9 21 ec e2 7c 9c 8c 23 14 40 6d 52 f9 40 f5 65 81 67 99 60 0c cd e2 e8 Decrypted Data (In hexadecimal format): af d4 00 50 00 00 00 00 00 00 00 00 50 02 20 00 87 df 00 00 48 65 6c 6c 6f 20 57 6f 72 6c 64 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 0f 06

Here, af d4 00 50 00 00 00 00 00 00 00 00 50 02 20 00 87 df 00 00, I am assuming these 20 bytes are IP header. But it is garbage. I cannot form IP header using these values. 48 65 6c 6c 6f 20 57 6f 72 6c 64 means Hello World (decrypted ESP Payload) 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 0f 06 is padding.

My command: echo <encrypted-esp-payload> | xxd -r -p | openssl aes-128-cbc -d -K <key> -iv <iv> -nopad | xxd -p

My Requirement: I need proper IPv4 header values after decryption, so that I can form a packet.

What should I do differently in command to get the correct IPv4 header values?

Openssl version: 3.0.2 IV and Key length: 16 bytes xxd: make a hexdump or do the reverse.

Scapy command:

sa = SecurityAssociation(ESP, spi=<spi>, crypt_algo='AES-CBC', crypt_key=b'<crypt_key>')
p = IP(src='1.1.1.1', dst='2.2.2.2')/TCP(sport=45012, dport=80)/Raw('Hello World')
p = IP(raw(p))
e = sa.encrypt(p, iv=b'<iv>')
sendp(Ether(src='00:11:22:33:44:55', dst='00:00:00:00:00:05')/e, iface="veth0")

Packet data:

11:34:15.121850 IP 1.1.1.1 > 2.2.2.2: ESP(spi=0xdeadbeef,seq=0x1), length 72
        0x0000:  4500 005c 0001 0000 4032 746a 0101 0101  E..\....@2tj....
        0x0010:  0202 0202 dead beef 0000 0001 6669 7865  ............fixe
        0x0020:  645f 6976 5f31 3662 7974 6573 df2d 4215  d_iv_16bytes.-B.
        0x0030:  29ca 6c77 9d60 03ef 4f1d faa9 57cf 6e29  ).lw.`..O...W.n)
        0x0040:  f0ad e7f8 668f 6c66 29a3 c4fe bc3c 57eb  ....f.lf)....<W.
        0x0050:  2f27 f997 9f81 59ac 2cf7 277b            /'....Y.,.'{

Solution

  • The Openssl decrypted it correctly. Since the scapy encrypts the packet in transport mode, the first 20 bytes are of TCP Header (NOT IP Header).

    af d4 00 50 00 00 00 00 00 00 00 00 50 02 20 00 19 14 00 00 is the TCP header.