OpenVPN
Data Structures | Macros | Functions
Data Channel Crypto module

Data Structures

struct  crypto_options
 Security parameter state for processing data channel packets. More...
 

Macros

#define TLS_AUTHENTICATED(multi, ks)   ((ks)->state >= (S_GOT_KEY - (multi)->opt.server))
 Check whether the ks key_state has finished the key exchange part of the OpenVPN hand shake. More...
 

Functions

enum first_packet_verdict tls_pre_decrypt_lite (const struct tls_auth_standalone *tas, struct tls_pre_decrypt_state *state, const struct link_socket_actual *from, const struct buffer *buf)
 Inspect an incoming packet for which no VPN tunnel is active, and determine whether a new VPN tunnel should be created. More...
 

Functions for performing security operations on data channel packets

void openvpn_encrypt (struct buffer *buf, struct buffer work, struct crypto_options *opt)
 Encrypt and HMAC sign a packet so that it can be sent as a data channel VPN tunnel packet to a remote OpenVPN peer. More...
 
bool openvpn_decrypt (struct buffer *buf, struct buffer work, struct crypto_options *opt, const struct frame *frame, const uint8_t *ad_start)
 HMAC verify and decrypt a data channel packet received from a remote OpenVPN peer. More...
 

Functions for managing security parameter state for data channel packets

void tls_pre_encrypt (struct tls_multi *multi, struct buffer *buf, struct crypto_options **opt)
 Choose the appropriate security parameters with which to process an outgoing packet. More...
 
struct key_statetls_select_encryption_key (struct tls_multi *multi)
 Selects the primary encryption that should be used to encrypt data of an outgoing packet. More...
 
void tls_prepend_opcode_v1 (const struct tls_multi *multi, struct buffer *buf)
 Prepend a one-byte OpenVPN data channel P_DATA_V1 opcode to the packet. More...
 
void tls_prepend_opcode_v2 (const struct tls_multi *multi, struct buffer *buf)
 Prepend an OpenVPN data channel P_DATA_V2 header to the packet. More...
 
void tls_post_encrypt (struct tls_multi *multi, struct buffer *buf)
 Perform some accounting for the key state used. More...
 

Detailed Description

The Data Channel Crypto Module performs cryptographic operations on data channel packets.

Security parameters
This module is merely the user of a VPN tunnel's security parameters. It does not perform the negotiation and setup of the security parameters, nor the key generation involved. These actions are done by the Control Channel Processor. This module receives the appropriate security parameters from that module in the form of a crypto_options structure when they are necessary for processing a packet.
Packet processing functions
This module receives data channel packets from the Data Channel Control module and processes them according to the security parameters of the packet's VPN tunnel. The Data Channel Control module uses the following interface functions:
Settings that control this module's activity
How the data channel processes packets received from the Data Channel Control module at runtime depends on the associated crypto_options structure. To perform cryptographic operations, the crypto_options.key_ctx_bi must contain the correct cipher and HMAC security parameters for the direction the packet is traveling in.
Crypto algorithms
This module uses the crypto algorithm implementations of the external crypto library (currently either OpenSSL (default), or mbed TLS).
Crypto packet formats
The Data Channel Crypto module supports a number of crypto modes and configurable options. The actual packet format depends on these options. A Data Channel packet can consist of:
  • Opcode, one byte specifying the packet type (see Network protocol).
  • Peer-id, if using the v2 data channel packet format (see Network protocol).
  • HMAC, covering the ciphertext IV + ciphertext. The HMAC size depends on the --auth option. If --auth none is specified, there is no HMAC at all.
  • Ciphertext IV. The IV size depends on the --cipher option.
  • Packet ID, a 32-bit incrementing packet counter that provides replay protection.
  • Timestamp, a 32-bit timestamp of the current time.
  • Payload, the plain text network packet to be encrypted (unless encryption is disabled by using --cipher none). The payload might already be compressed (see Compression module).
This section does not discuss the opcode and peer-id, since those do not depend on the data channel crypto. See Network protocol for more information on those.
Legenda
[ xxx ] = unprotected
[ - xxx - ] = authenticated
[ * xxx * ] = encrypted and authenticated
CBC data channel cypto format
In CBC mode, both TLS-mode and static key mode are supported. The IV consists of random bits to provide unpredictable IVs.
CBC IV format:
[ - random - ]
CBC data channel crypto format in TLS-mode:
[ HMAC ] [ - IV - ] [ * packet ID * ] [ * packet payload * ]
CBC data channel crypto format in static key mode:
[ HMAC ] [ - IV - ] [ * packet ID * ] [ * timestamp * ] [ * packet payload * ]
CFB/OFB data channel crypto format
CFB and OFB modes are only supported in TLS mode. In these modes, the IV consists of the packet counter and a timestamp. If the IV is more than 8 bytes long, the remaining space is filled with zeroes. The packet counter may not roll over within a single TLS sessions. This results in a unique IV for each packet, as required by the CFB and OFB cipher modes.
CFB/OFB IV format:
[ - packet ID - ] [ - timestamp - ] [ - opt: zero-padding - ]
CFB/OFB data channel crypto format:
[ HMAC ] [ - IV - ] [ * packet payload * ]
GCM data channel crypto format
GCM modes are only supported in TLS mode. In these modes, the IV consists of the 32-bit packet counter followed by data from the HMAC key. The HMAC key can be used as IV, since in GCM and CCM modes the HMAC key is not used for the HMAC. The packet counter may not roll over within a single TLS sessions. This results in a unique IV for each packet, as required by GCM.
The HMAC key data is pre-shared during the connection setup, and thus can be omitted in on-the-wire packets, saving 8 bytes per packet (for GCM and CCM).
In GCM mode, P_DATA_V2 headers (the opcode and peer-id) are also authenticated as Additional Data.
GCM IV format:
[ - packet ID - ] [ - HMAC key data - ]
P_DATA_V1 GCM data channel crypto format:
[ opcode ] [ - packet ID - ] [ TAG ] [ * packet payload * ] P_DATA_V2 GCM data channel crypto format:
[ - opcode/peer-id - ] [ - packet ID - ] [ TAG ] [ * packet payload * ]
No-crypto data channel format
In no-crypto mode (--cipher none is specified), both TLS-mode and static key mode are supported. No encryption will be performed on the packet, but packets can still be authenticated. This mode does not require an IV.
No-crypto data channel crypto format in TLS-mode:
[ HMAC ] [ - packet ID - ] [ - packet payload - ]
No-crypto data channel crypto format in static key mode:
[ HMAC ] [ - packet ID - ] [ - timestamp - ] [ - packet payload - ]

Macro Definition Documentation

◆ TLS_AUTHENTICATED

#define TLS_AUTHENTICATED (   multi,
  ks 
)    ((ks)->state >= (S_GOT_KEY - (multi)->opt.server))

Check whether the ks key_state has finished the key exchange part of the OpenVPN hand shake.

This is that the key_method_2read/write handshakes have been completed and certificate verification have been completed.

connect/deferred auth might still pending. Also data-channel keys might not have been created since they are delayed until PUSH_REPLY for NCP clients.

If true, it is safe to assume that this session has been authenticated by TLS.

Note
This macro only works if S_SENT_KEY + 1 == S_GOT_KEY.

Definition at line 109 of file ssl_verify.h.

Function Documentation

◆ openvpn_decrypt()

bool openvpn_decrypt ( struct buffer buf,
struct buffer  work,
struct crypto_options opt,
const struct frame frame,
const uint8_t *  ad_start 
)

HMAC verify and decrypt a data channel packet received from a remote OpenVPN peer.

This function handles authenticating and decrypting a data channel packet received from a remote OpenVPN peer. It receives the necessary security parameters in the opt argument, which should have been set to the correct values by the tls_pre_decrypt() function.

This function calls the EVP_Cipher* and HMAC_* functions of the OpenSSL library to perform the actual security operations.

If an error occurs during processing, then the buf buffer is set to empty.

Parameters
buf- The buffer containing the packet received from a remote OpenVPN peer on which to perform security operations.
work- A working buffer.
opt- The security parameter state for this VPN tunnel.
frame- The packet geometry parameters for this VPN tunnel.
ad_start- A pointer into buf, indicating from where to start authenticating additional data (AEAD mode only).
Returns
  • True, if the packet was authenticated and decrypted successfully.
  • False, if an error occurred.
    On return, the buf argument will point to the resulting buffer. This buffer will either contain the plaintext packet ready for further processing, or be empty if an error occurred.

Definition at line 645 of file crypto.c.

References key_ctx::cipher, cipher_ctx_mode_aead(), key_ctx_bi::decrypt, crypto_options::key_ctx_bi, buffer::len, openvpn_decrypt_aead(), and openvpn_decrypt_v1().

Referenced by process_incoming_link_part1(), read_control_auth(), and test_crypto().

◆ openvpn_encrypt()

void openvpn_encrypt ( struct buffer buf,
struct buffer  work,
struct crypto_options opt 
)

Encrypt and HMAC sign a packet so that it can be sent as a data channel VPN tunnel packet to a remote OpenVPN peer.

This function handles encryption and HMAC signing of a data channel packet before it is sent to its remote OpenVPN peer. It receives the necessary security parameters in the opt argument, which should have been set to the correct values by the tls_pre_encrypt() function.

This function calls the EVP_Cipher* and HMAC_* functions of the OpenSSL library to perform the actual security operations.

If an error occurs during processing, then the buf buffer is set to empty.

Parameters
buf- The buffer containing the packet on which to perform security operations.
work- An initialized working buffer.
opt- The security parameter state for this VPN tunnel.
Returns
This function returns void.
On return, the buf argument will point to the resulting buffer. This buffer will either contain the processed packet ready for sending, or be empty if an error occurred.

Definition at line 295 of file crypto.c.

References key_ctx::cipher, cipher_ctx_mode_aead(), key_ctx_bi::encrypt, crypto_options::key_ctx_bi, buffer::len, openvpn_encrypt_aead(), and openvpn_encrypt_v1().

Referenced by encrypt_sign(), test_crypto(), and tls_wrap_control().

◆ tls_post_encrypt()

void tls_post_encrypt ( struct tls_multi multi,
struct buffer buf 
)

Perform some accounting for the key state used.

Parameters
multi- The TLS state for this packet's destination VPN tunnel.
buf- The buffer containing the outgoing packet.

Definition at line 3909 of file ssl.c.

References ASSERT, buffer::len, key_state::n_bytes, key_state::n_packets, and tls_multi::save_ks.

Referenced by encrypt_sign().

◆ tls_pre_decrypt_lite()

enum first_packet_verdict tls_pre_decrypt_lite ( const struct tls_auth_standalone tas,
struct tls_pre_decrypt_state state,
const struct link_socket_actual from,
const struct buffer buf 
)

Inspect an incoming packet for which no VPN tunnel is active, and determine whether a new VPN tunnel should be created.

This function receives the initial incoming packet from a client that wishes to establish a new VPN tunnel, and determines the packet is a valid initial packet. It is only used when OpenVPN is running in server mode.

The tests performed by this function are whether the packet's opcode is correct for establishing a new VPN tunnel, whether its key ID is 0, and whether its size is not too large. This function also performs the initial HMAC firewall test, if configured to do so.

The incoming packet and the local VPN tunnel state are not modified by this function. Its sole purpose is to inspect the packet and determine whether a new VPN tunnel should be created. If so, that new VPN tunnel instance will handle processing of the packet.

This function is only used in the UDP p2mp server code path

Parameters
tas- The standalone TLS authentication setting structure for this process.
from- The source address of the packet.
buf- A buffer structure containing the incoming packet.
Returns
  • True if the packet is valid and a new VPN tunnel should be created for this client.
  • False if the packet is not valid, did not pass the HMAC firewall test, or some other error occurred.

Definition at line 307 of file ssl_pkt.c.

References BPTR, buf_advance(), clone_buf(), D_TLS_ERRORS, D_TLS_STATE_ERRORS, dmsg, gc_free(), gc_new(), buffer::len, msg, tls_pre_decrypt_state::newbuf, P_ACK_V1, P_CONTROL_HARD_RESET_CLIENT_V2, P_CONTROL_HARD_RESET_CLIENT_V3, P_CONTROL_V1, P_CONTROL_WKC_V1, P_KEY_ID_MASK, P_OPCODE_SHIFT, tls_pre_decrypt_state::peer_session_id, print_link_socket_actual(), read_control_auth(), session_id_defined(), session_id_read(), SID_SIZE, status, tls_clear_error(), tls_auth_standalone::tls_wrap, tls_pre_decrypt_state::tls_wrap_tmp, VERDICT_INVALID, VERDICT_VALID_ACK_V1, VERDICT_VALID_CONTROL_V1, VERDICT_VALID_RESET_V2, VERDICT_VALID_RESET_V3, and VERDICT_VALID_WKC_V1.

Referenced by do_pre_decrypt_check(), test_generate_reset_packet_plain(), test_generate_reset_packet_tls_auth(), test_tls_decrypt_lite_auth(), test_tls_decrypt_lite_crypt(), test_tls_decrypt_lite_none(), test_verify_hmac_none(), and test_verify_hmac_tls_auth().

◆ tls_pre_encrypt()

void tls_pre_encrypt ( struct tls_multi multi,
struct buffer buf,
struct crypto_options **  opt 
)

Choose the appropriate security parameters with which to process an outgoing packet.

If no appropriate security parameters can be found, or if some other error occurs, then the buffer is set to empty, and the parameters to a NULL pointer.

Parameters
multi- The TLS state for this packet's destination VPN tunnel.
buf- The buffer containing the outgoing packet.
opt- Returns a crypto options structure with the security parameters.

Definition at line 3847 of file ssl.c.

References key_state::crypto_options, D_TLS_KEYSELECT, dmsg, gc_free(), gc_new(), key_state::key_id, buffer::len, print_key_id(), tls_multi::save_ks, and tls_select_encryption_key().

Referenced by encrypt_sign().

◆ tls_prepend_opcode_v1()

void tls_prepend_opcode_v1 ( const struct tls_multi multi,
struct buffer buf 
)

Prepend a one-byte OpenVPN data channel P_DATA_V1 opcode to the packet.

The opcode identifies the packet as a V1 data channel packet and gives the low-permutation version of the key-id to the recipient, so it knows which decrypt key to use.

Parameters
multi- The TLS state for this packet's destination VPN tunnel.
buf- The buffer to write the header to.

Definition at line 3880 of file ssl.c.

References ASSERT, buf_write_prepend(), D_TLS_DEBUG, key_state::key_id, msg, P_DATA_V1, P_OPCODE_SHIFT, and tls_multi::save_ks.

Referenced by encrypt_sign().

◆ tls_prepend_opcode_v2()

void tls_prepend_opcode_v2 ( const struct tls_multi multi,
struct buffer buf 
)

Prepend an OpenVPN data channel P_DATA_V2 header to the packet.

The P_DATA_V2 header consists of a 1-byte opcode, followed by a 3-byte peer-id.

The opcode identifies the packet as a V2 data channel packet and gives the low-permutation version of the key-id to the recipient, so it knows which decrypt key to use.

The peer-id is sent by clients to servers to help the server determine to select the decrypt key when the client is roaming between addresses/ports.

Parameters
multi- The TLS state for this packet's destination VPN tunnel.
buf- The buffer to write the header to.

Definition at line 3894 of file ssl.c.

References ASSERT, buf_write_prepend(), D_TLS_DEBUG, key_state::key_id, msg, P_DATA_V2, P_OPCODE_SHIFT, tls_multi::peer_id, and tls_multi::save_ks.

Referenced by encrypt_sign().

◆ tls_select_encryption_key()

struct key_state* tls_select_encryption_key ( struct tls_multi multi)

Selects the primary encryption that should be used to encrypt data of an outgoing packet.

If no key is found NULL is returned instead.

Parameters
multi- The TLS state for this packet's destination VPN tunnel.

Definition at line 3820 of file ssl.c.

References ASSERT, key_state::auth_deferred_expire, key_state::authenticated, key_state::crypto_options, get_key_scan(), key_ctx_bi::initialized, crypto_options::key_ctx_bi, KEY_SCAN_SIZE, KS_AUTH_TRUE, now, S_GENERATED_KEYS, and key_state::state.

Referenced by tls_pre_encrypt().