Update: I've been able to work out everything I was asking about packet structure when I was finally able to get Wireshark to work, but there is one last thing I'm confused on which I detail at the end of the question.
Original question: I'm new to networking and have been reading into how OpenVPN constructs its packets and a bit more of the technical details of how tls-auth is implemented. From what I have read, all the packets for the TLS handshake are protected with a HMAC signature, for which the key used to produce this signature is derived from the static key given in a client config.
There are a few things that are confusing me though, so I just have a few questions:
At first, I believed only the packets used for authenticating with TLS (hence the option name) are given this HMAC signature, however on OpenVPN's protocol page it states:
* P_CONTROL message format: * * local session_id (random 64 bit value to identify TLS session). * HMAC signature of entire encapsulation header for integrity * check if --tls-auth is specified (usually 16 or 20 bytes). ... Note that when --tls-auth is used, all message types are * protected with an HMAC signature, even the initial packets * of the TLS handshake.
It words this as if this HMAC is used for all packets in the control channel when tls-auth is specified, not just those in the initial TLS handshake. Is that the case?
Secondly, how are the keys that are used to sign and verify these packets with HMAC actually derived from the static key? I assume the key is split into 4 separate parts of 64 chars, but which part is used for what?
Finally, where would the HMAC signature actually be placed in these packets? I have took a look at an old, easier to process OpenVPN client library that doesn't use tls-auth or tls-crypt (still works on the latest OpenVPN server version), and it seems to structure its packets like:
data = (Packet Header + Session Id) data.append(0) data.append(packetId) data.append(payload)
The structure vaguely seems to resemble that in the protocol page. Would placing the HMAC in this packet be as simple as:
data = (Packet Header + Session Id) data.append(HMACOf(PacketHeader)) data.append(0) data.append(packetId) data.append(payload)
Or would it be inside the appended payload?
Update: Okay so now I know that it is all the control channel packets that use this additional HMAC. I've also been able to check the packet structure properly, and with tls-auth there seems to be an extra HMAC, packet ID, and 'net time' appended after the session ID. I've discovered that the key derived for HMAC production from the static key is 4 lines down when no key direction is specified, with the length of the key being respective of the auth type (eg: 160 bits worth of chars for SHA1) from here. The only thing left on my mind is what parts of the packet count as the "encapsulation header" from which the HMAC is calculated.