Split TCP packets in pcap file

Sometimes, to simulate one corner case, i.e., the TCP layer splits one application record into multiple packets, I need to use libpcap to tweak pcap files. E.g., for following diagram:

I split frame 8 into 3 parts, one will be appended to frame 7, and the remaining 2 parts will be 2 separated packets.

Generally speaking, only length field in IP header and Sequence number field in TCP header need to be modified. The source code and pcap file can be referenced here.

Create IETF QUIC pcap file

I couldn’t find some off-the-shelf QUIC pcap files which conform to IETF draft versions, so I decided to create them myself. Take Client Initial packet in draft-29 as an example:

(1) Copy following raw packet info into payload.txt:

c5ff00001d088394c8f03e5157080000 449e4a95245bfb66bc5f93032b7ddd89
fe0ff15d9c4f7050fccdb71c1cd80512 d4431643a53aafa1b0b518b44968b18b
......

Use awk command to create string from payload.txt:

$ awk '{for (i = 1; i <= NF; i++) {printf("\"%s\"\n", $i)}}' payload.txt
"c5ff00001d088394c8f03e5157080000"
"449e4a95245bfb66bc5f93032b7ddd89"
"fe0ff15d9c4f7050fccdb71c1cd80512"
"d4431643a53aafa1b0b518b44968b18b"
......

(2) Use a C program to generate payload array:

#include <stdio.h>

char payload[] =
"c5ff00001d088394c8f03e5157080000"
"449e4a95245bfb66bc5f93032b7ddd89"
......
;

int main(void) {
    size_t count = 0;
    printf("const uint8_t payload[] = {\n");
    for (size_t i = 0; i < strlen(payload); i += 2) {
        printf("0x%c%c,", payload[i], payload[i + 1]);
        if (++count == 8) {
            count = 0;
            printf("\n");
        } else {
            printf(" ");
        }
    }
        printf("};");
    return 0;
}

(3) Forge ethernetIP and UDP headers and use libpcap APIs to generate pcap file. The code can be referred here.

Duplicate EVP_MD structure when necessary

Many openssl APIs return const EVP_MD pointers (e.g., EVP_sha256), and sometimes you need to resolve following errors:

error: cast discards 'const' qualifier from pointer target type [-Werror=cast-qual]

You can either suppress the warning like this or duplicate EVP_MD:

EVP_MD *md = EVP_MD_meth_dup(EVP_sha256());
......
EVP_MD_meth_free(md);

Use openssl APIs to generate initial secrets of QUIC

From QUIC draft 29:

The secrets for the Initial encryption level are computed based on the client’s initial Destination Connection ID, as described in Section 5.2.

There is also an example about the secrets of initial packets, and I used openssl APIs to demonstrate it:

# ./main
initial_secret(32): 1e7e7764529715b1e0ddc8e9753c61576769605187793ed366f8bbf8c9e986eb
client_in_secret(32): 0088119288f1d866733ceeed15ff9d50902cf82952eee27e9d4d4918ea371d87
quic_key(16): 175257a31eb09dea9366d8bb79ad80ba
quic_iv(12): 6b26114b9cba2b63a9e8dd4f
quic_hp(16): 9ddd12c994c0698b89374a9c077a3077

P.S., the code can be downloaded here.

References:
What am I doing wrong?;
HKDF context re-use issue;
HKDF实现.