aboutsummaryrefslogtreecommitdiff
path: root/ssl.h
diff options
context:
space:
mode:
Diffstat (limited to 'ssl.h')
-rw-r--r--ssl.h528
1 files changed, 310 insertions, 218 deletions
diff --git a/ssl.h b/ssl.h
index 790a57e..5694782 100644
--- a/ssl.h
+++ b/ssl.h
@@ -22,6 +22,12 @@
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
+/**
+ * @file header file
+ */
+
+
#ifndef OPENVPN_SSL_H
#define OPENVPN_SSL_H
@@ -45,153 +51,6 @@
#include "options.h"
#include "plugin.h"
-/*
- * OpenVPN Protocol, taken from ssl.h in OpenVPN source code.
- *
- * TCP/UDP Packet: This represents the top-level encapsulation.
- *
- * TCP/UDP packet format:
- *
- * Packet length (16 bits, unsigned) -- TCP only, always sent as
- * plaintext. Since TCP is a stream protocol, the packet
- * length words define the packetization of the stream.
- *
- * Packet opcode/key_id (8 bits) -- TLS only, not used in
- * pre-shared secret mode.
- * packet message type, a P_* constant (high 5 bits)
- * key_id (low 3 bits, see key_id in struct tls_session
- * below for comment). The key_id refers to an
- * already negotiated TLS session. OpenVPN seamlessly
- * renegotiates the TLS session by using a new key_id
- * for the new session. Overlap (controlled by
- * user definable parameters) between old and new TLS
- * sessions is allowed, providing a seamless transition
- * during tunnel operation.
- *
- * Payload (n bytes), which may be a P_CONTROL, P_ACK, or P_DATA
- * message.
- *
- * Message types:
- *
- * P_CONTROL_HARD_RESET_CLIENT_V1 -- Key method 1, initial key from
- * client, forget previous state.
- *
- * P_CONTROL_HARD_RESET_SERVER_V1 -- Key method 2, initial key
- * from server, forget previous state.
- *
- * P_CONTROL_SOFT_RESET_V1 -- New key, with a graceful transition
- * from old to new key in the sense that a transition window
- * exists where both the old or new key_id can be used. OpenVPN
- * uses two different forms of key_id. The first form is 64 bits
- * and is used for all P_CONTROL messages. P_DATA messages on the
- * other hand use a shortened key_id of 3 bits for efficiency
- * reasons since the vast majority of OpenVPN packets in an
- * active tunnel will be P_DATA messages. The 64 bit form
- * is referred to as a session_id, while the 3 bit form is
- * referred to as a key_id.
- *
- * P_CONTROL_V1 -- Control channel packet (usually TLS ciphertext).
- *
- * P_ACK_V1 -- Acknowledgement for P_CONTROL packets received.
- *
- * P_DATA_V1 -- Data channel packet containing actual tunnel data
- * ciphertext.
- *
- * P_CONTROL_HARD_RESET_CLIENT_V2 -- Key method 2, initial key from
- * client, forget previous state.
- *
- * P_CONTROL_HARD_RESET_SERVER_V2 -- Key method 2, initial key from
- * server, forget previous state.
- *
- * P_CONTROL* and P_ACK Payload: The P_CONTROL message type
- * indicates a TLS ciphertext packet which has been encapsulated
- * inside of a reliability layer. The reliability layer is
- * implemented as a straightforward ACK and retransmit model.
- *
- * 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).
- * packet-id for replay protection (4 or 8 bytes, includes
- * sequence number and optional time_t timestamp).
- * P_ACK packet_id array length (1 byte).
- * P_ACK packet-id array (if length > 0).
- * P_ACK remote session_id (if length > 0).
- * message packet-id (4 bytes).
- * TLS payload ciphertext (n bytes) (only for P_CONTROL).
- *
- * Once the TLS session has been initialized and authenticated,
- * the TLS channel is used to exchange random key material for
- * bidirectional cipher and HMAC keys which will be
- * used to secure actual tunnel packets. OpenVPN currently
- * implements two key methods. Key method 1 directly
- * derives keys using random bits obtained from the RAND_bytes
- * OpenSSL function. Key method 2 mixes random key material
- * from both sides of the connection using the TLS PRF mixing
- * function. Key method 2 is the preferred method and is the default
- * for OpenVPN 2.0.
- *
- * TLS plaintext content:
- *
- * TLS plaintext packet (if key_method == 1):
- *
- * Cipher key length in bytes (1 byte).
- * Cipher key (n bytes).
- * HMAC key length in bytes (1 byte).
- * HMAC key (n bytes).
- * Options string (n bytes, null terminated, client/server options
- * string should match).
- *
- * TLS plaintext packet (if key_method == 2):
- *
- * Literal 0 (4 bytes).
- * key_method type (1 byte).
- * key_source structure (pre_master only defined for client ->
- * server).
- * options_string_length, including null (2 bytes).
- * Options string (n bytes, null terminated, client/server options
- * string must match).
- * [The username/password data below is optional, record can end
- * at this point.]
- * username_string_length, including null (2 bytes).
- * Username string (n bytes, null terminated).
- * password_string_length, including null (2 bytes).
- * Password string (n bytes, null terminated).
- *
- * The P_DATA payload represents encrypted, encapsulated tunnel
- * packets which tend to be either IP packets or Ethernet frames.
- * This is essentially the "payload" of the VPN.
- *
- * P_DATA message content:
- * HMAC of ciphertext IV + ciphertext (if not disabled by
- * --auth none).
- * Ciphertext IV (size is cipher-dependent, if not disabled by
- * --no-iv).
- * Tunnel packet ciphertext.
- *
- * P_DATA plaintext
- * packet_id (4 or 8 bytes, if not disabled by --no-replay).
- * In SSL/TLS mode, 4 bytes are used because the implementation
- * can force a TLS renegotation before 2^32 packets are sent.
- * In pre-shared key mode, 8 bytes are used (sequence number
- * and time_t value) to allow long-term key usage without
- * packet_id collisions.
- * User plaintext (n bytes).
- *
- * Notes:
- * (1) ACK messages can be encoded in either the dedicated
- * P_ACK record or they can be prepended to a P_CONTROL message.
- * (2) P_DATA and P_CONTROL/P_ACK use independent packet-id
- * sequences because P_DATA is an unreliable channel while
- * P_CONTROL/P_ACK is a reliable channel. Each use their
- * own independent HMAC keys.
- * (3) Note that when --tls-auth is used, all message types are
- * protected with an HMAC signature, even the initial packets
- * of the TLS handshake. This makes it easy for OpenVPN to
- * throw away bogus packets quickly, without wasting resources
- * on attempting a TLS handshake which will ultimately fail.
- */
/* Used in the TLS PRF function */
#define KEY_EXPANSION_ID "OpenVPN"
@@ -220,28 +79,82 @@
#define P_FIRST_OPCODE 1
#define P_LAST_OPCODE 8
-/* key negotiation states */
-#define S_ERROR -1
-#define S_UNDEF 0
-#define S_INITIAL 1 /* tls_init() was called */
-#define S_PRE_START 2 /* waiting for initial reset & acknowledgement */
-#define S_START 3 /* ready to exchange keys */
-#define S_SENT_KEY 4 /* client does S_SENT_KEY -> S_GOT_KEY */
-#define S_GOT_KEY 5 /* server does S_GOT_KEY -> S_SENT_KEY */
-#define S_ACTIVE 6 /* ready to exchange data channel packets */
-#define S_NORMAL_OP 7 /* normal operations */
-
-/*
- * Are we ready to receive data channel packets?
- *
- * Also, if true, we can safely assume session has been
- * authenticated by TLS.
- *
- * NOTE: Assumes S_SENT_KEY + 1 == S_GOT_KEY.
+/** @addtogroup control_processor
+ * @{ */
+/**
+ * @name Control channel negotiation states
+ *
+ * These states represent the different phases of control channel
+ * negotiation between OpenVPN peers. OpenVPN servers and clients
+ * progress through the states in a different order, because of their
+ * different roles during exchange of random material. The references to
+ * the \c key_source2 structure in the list below is only valid if %key
+ * method 2 is being used. See the \link key_generation data channel key
+ * generation\endlink related page for more information.
+ *
+ * Clients follow this order:
+ * -# \c S_INITIAL, ready to begin three-way handshake and control
+ * channel negotiation.
+ * -# \c S_PRE_START, have started three-way handshake, waiting for
+ * acknowledgment from remote.
+ * -# \c S_START, initial three-way handshake complete.
+ * -# \c S_SENT_KEY, have sent local part of \c key_source2 random
+ * material.
+ * -# \c S_GOT_KEY, have received remote part of \c key_source2 random
+ * material.
+ * -# \c S_ACTIVE, normal operation during remaining handshake window.
+ * -# \c S_NORMAL_OP, normal operation.
+ *
+ * Servers follow the same order, except for \c S_SENT_KEY and \c
+ * S_GOT_KEY being reversed, because the server first receives the
+ * client's \c key_source2 random material before generating and sending
+ * its own.
+ *
+ * @{
*/
-#define DECRYPT_KEY_ENABLED(multi, ks) ((ks)->state >= (S_GOT_KEY - (multi)->opt.server))
+#define S_ERROR -1 /**< Error state. */
+#define S_UNDEF 0 /**< Undefined state, used after a \c
+ * key_state is cleaned up. */
+#define S_INITIAL 1 /**< Initial \c key_state state after
+ * initialization by \c key_state_init()
+ * before start of three-way handshake. */
+#define S_PRE_START 2 /**< Waiting for the remote OpenVPN peer
+ * to acknowledge during the initial
+ * three-way handshake. */
+#define S_START 3 /**< Three-way handshake is complete,
+ * start of key exchange. */
+#define S_SENT_KEY 4 /**< Local OpenVPN process has sent its
+ * part of the key material. */
+#define S_GOT_KEY 5 /**< Local OpenVPN process has received
+ * the remote's part of the key
+ * material. */
+#define S_ACTIVE 6 /**< Operational \c key_state state
+ * immediately after negotiation has
+ * completed while still within the
+ * handshake window. */
+/* ready to exchange data channel packets */
+#define S_NORMAL_OP 7 /**< Normal operational \c key_state
+ * state. */
+/** @} name Control channel negotiation states */
+/** @} addtogroup control_processor */
-/* Should we aggregate TLS acknowledgements, and tack them onto control packets? */
+
+#define DECRYPT_KEY_ENABLED(multi, ks) ((ks)->state >= (S_GOT_KEY - (multi)->opt.server))
+ /**< Check whether the \a ks \c key_state
+ * is ready to receive data channel
+ * packets.
+ * @ingroup data_crypto
+ *
+ * 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. */
+
+/* Should we aggregate TLS
+ * acknowledgements, and tack them onto
+ * control packets? */
#define TLS_AGGREGATE_ACK
/*
@@ -319,33 +232,50 @@ struct cert_hash_set {
struct cert_hash *ch[MAX_CERT_DEPTH];
};
-/*
- * Key material, used as source for PRF-based
- * key expansion.
+/**
+ * Container for one half of random material to be used in %key method 2
+ * \ref key_generation "data channel key generation".
+ * @ingroup control_processor
*/
-
struct key_source {
- uint8_t pre_master[48]; /* client generated */
- uint8_t random1[32]; /* generated by both client and server */
- uint8_t random2[32]; /* generated by both client and server */
+ uint8_t pre_master[48]; /**< Random used for master secret
+ * generation, provided only by client
+ * OpenVPN peer. */
+ uint8_t random1[32]; /**< Seed used for master secret
+ * generation, provided by both client
+ * and server. */
+ uint8_t random2[32]; /**< Seed used for key expansion, provided
+ * by both client and server. */
};
+
+/**
+ * Container for both halves of random material to be used in %key method
+ * 2 \ref key_generation "data channel key generation".
+ * @ingroup control_processor
+ */
struct key_source2 {
- struct key_source client;
- struct key_source server;
+ struct key_source client; /**< Random provided by client. */
+ struct key_source server; /**< Random provided by server. */
};
-/*
- * Represents a single instantiation of a TLS negotiation and
- * data channel key exchange. 4 keys are kept: encrypt hmac,
- * decrypt hmac, encrypt cipher, and decrypt cipher. The TLS
- * control channel is used to exchange these keys.
- * Each hard or soft reset will build
- * a fresh key_state. Normally an openvpn session will contain two
- * key_state objects, one for the current TLS connection, and other
- * for the retiring or "lame duck" key. The lame duck key_state is
- * used to maintain transmission continuity on the data-channel while
- * a key renegotiation is taking place.
+/**
+ * Security parameter state of one TLS and data channel %key session.
+ * @ingroup control_processor
+ *
+ * This structure represents one security parameter session between
+ * OpenVPN peers. It includes the control channel TLS state and the data
+ * channel crypto state. It also contains the reliability layer
+ * structures used for control channel messages.
+ *
+ * A new \c key_state structure is initialized for each hard or soft
+ * reset.
+ *
+ * @see
+ * - This structure should be initialized using the \c key_state_init()
+ * function.
+ * - This structure should be cleaned up using the \c key_state_free()
+ * function.
*/
struct key_state
{
@@ -523,23 +453,37 @@ struct tls_options
int gremlin;
};
-/* index into tls_session.key */
-#define KS_PRIMARY 0 /* the primary key */
-#define KS_LAME_DUCK 1 /* the key that's going to retire soon */
-#define KS_SIZE 2
-/*
- * A tls_session lives through multiple key_state life-cycles. Soft resets
- * will reuse a tls_session object, but hard resets or errors will require
- * that a fresh object be built. Normally three tls_session objects are maintained
- * by an active openvpn session. The first is the current, TLS authenticated
- * session, the second is used to process connection requests from a new
- * client that would usurp the current session if successfully authenticated,
- * and the third is used as a repository for a "lame-duck" key in the event
- * that the primary session resets due to error while the lame-duck key still
- * has time left before its expiration. Lame duck keys are used to maintain
- * the continuity of the data channel connection while a new key is being
- * negotiated.
+/** @addtogroup control_processor
+ * @{ */
+/** @name Index of key_state objects within a tls_session structure
+ *
+ * This is the index of \c tls_session.key
+ *
+ * @{ */
+#define KS_PRIMARY 0 /**< Primary %key state index. */
+#define KS_LAME_DUCK 1 /**< %Key state index that will retire
+ * soon. */
+#define KS_SIZE 2 /**< Size of the \c tls_session.key array. */
+/** @} name Index of key_state objects within a tls_session structure */
+/** @} addtogroup control_processor */
+
+
+/**
+ * Security parameter state of a single session within a VPN tunnel.
+ * @ingroup control_processor
+ *
+ * This structure represents an OpenVPN peer-to-peer control channel
+ * session.
+ *
+ * A \c tls_session remains over soft resets, but a new instance is
+ * initialized for each hard reset.
+ *
+ * @see
+ * - This structure should be initialized using the \c tls_session_init()
+ * function.
+ * - This structure should be cleaned up using the \c tls_session_free()
+ * function.
*/
struct tls_session
{
@@ -577,11 +521,34 @@ struct tls_session
struct key_state key[KS_SIZE];
};
-/* index into tls_multi.session */
-#define TM_ACTIVE 0
-#define TM_UNTRUSTED 1
-#define TM_LAME_DUCK 2
-#define TM_SIZE 3
+
+
+/** @addtogroup control_processor
+ * @{ */
+/** @name Index of tls_session objects within a tls_multi structure
+ *
+ * This is the index of \c tls_multi.session
+ *
+ * Normally three tls_session objects are maintained by an active openvpn
+ * session. The first is the current, TLS authenticated session, the
+ * second is used to process connection requests from a new client that
+ * would usurp the current session if successfully authenticated, and the
+ * third is used as a repository for a "lame-duck" %key in the event that
+ * the primary session resets due to error while the lame-duck %key still
+ * has time left before its expiration. Lame duck keys are used to
+ * maintain the continuity of the data channel connection while a new %key
+ * is being negotiated.
+ *
+ * @{ */
+#define TM_ACTIVE 0 /**< Active \c tls_session. */
+#define TM_UNTRUSTED 1 /**< As yet un-trusted \c tls_session
+ * being negotiated. */
+#define TM_LAME_DUCK 2 /**< Old \c tls_session. */
+#define TM_SIZE 3 /**< Size of the \c tls_multi.session
+ * array. */
+/** @} name Index of tls_session objects within a tls_multi structure */
+/** @} addtogroup control_processor */
+
/*
* The number of keys we will scan on encrypt or decrypt. The first
@@ -595,19 +562,29 @@ struct tls_session
*/
#define KEY_SCAN_SIZE 3
-/*
- * An openvpn session running with TLS enabled has one tls_multi object.
+
+/**
+ * Security parameter state for a single VPN tunnel.
+ * @ingroup control_processor
+ *
+ * An active VPN tunnel running with TLS enabled has one \c tls_multi
+ * object, in which it stores all control channel and data channel
+ * security parameter state. This structure can contain multiple,
+ * possibly simultaneously active, \c tls_context objects to allow for
+ * interruption-less transitions during session renegotiations. Each \c
+ * tls_context represents one control channel session, which can span
+ * multiple data channel security parameter sessions stored in \c
+ * key_state structures.
*/
struct tls_multi
{
/* const options and config info */
struct tls_options opt;
- /*
- * A list of key_state objects in the order they should be
- * scanned by data channel encrypt and decrypt routines.
- */
struct key_state* key_scan[KEY_SCAN_SIZE];
+ /**< List of \c key_state objects in the
+ * order they should be scanned by data
+ * channel modules. */
/*
* used by tls_pre_encrypt to communicate the encrypt key
@@ -621,10 +598,8 @@ struct tls_multi
*/
struct link_socket_actual to_link_addr;
- /*
- * Number of sessions negotiated thus far.
- */
- int n_sessions;
+ int n_sessions; /**< Number of sessions negotiated thus
+ * far. */
/*
* Number of errors.
@@ -659,6 +634,9 @@ struct tls_multi
* Our session objects.
*/
struct tls_session session[TM_SIZE];
+ /**< Array of \c tls_session objects
+ * representing control channel
+ * sessions with the remote peer. */
};
/*
@@ -704,20 +682,134 @@ int tls_multi_process (struct tls_multi *multi,
void tls_multi_free (struct tls_multi *multi, bool clear);
+
+/**************************************************************************/
+/**
+ * Determine whether an incoming packet is a data channel or control
+ * channel packet, and process accordingly.
+ * @ingroup external_multiplexer
+ *
+ * When OpenVPN is in TLS mode, this is the first function to process an
+ * incoming packet. It inspects the packet's one-byte header which
+ * contains the packet's opcode and key ID. Depending on the opcode, the
+ * packet is processed as a data channel or as a control channel packet.
+ *
+ * @par Data channel packets
+ *
+ * If the opcode indicates the packet is a data channel packet, then the
+ * packet's key ID is used to find the local TLS state it is associated
+ * with. This state is checked whether it is active, authenticated, and
+ * its remote peer is the source of this packet. If these checks passed,
+ * the state's security parameters are loaded into the \a opt crypto
+ * options so that \p openvpn_decrypt() can later use them to authenticate
+ * and decrypt the packet.
+ *
+ * This function then returns false. The \a buf buffer has not been
+ * modified, except for removing the header.
+ *
+ * @par Control channel packets
+ *
+ * If the opcode indicates the packet is a control channel packet, then
+ * this function will process it based on its plaintext header. depending
+ * on the packet's opcode and session ID this function determines if it is
+ * destined for an active TLS session, or whether a new TLS session should
+ * be started. This function also initiates data channel session key
+ * renegotiation if the received opcode requests that.
+ *
+ * If the incoming packet is destined for an active TLS session, then the
+ * packet is inserted into the Reliability Layer and will be handled
+ * later.
+ *
+ * @param multi - The TLS multi structure associated with the VPN tunnel
+ * of this packet.
+ * @param from - The source address of the packet.
+ * @param buf - A buffer structure containing the incoming packet.
+ * @param opt - A crypto options structure that will be loaded with the
+ * appropriate security parameters to handle the packet if it is a
+ * data channel packet.
+ *
+ * @return
+ * @li True if the packet is a control channel packet that has been
+ * processed successfully.
+ * @li False if the packet is a data channel packet, or if an error
+ * occurred during processing of a control channel packet.
+ */
bool tls_pre_decrypt (struct tls_multi *multi,
const struct link_socket_actual *from,
struct buffer *buf,
struct crypto_options *opt);
+
+/**************************************************************************/
+/** @name Functions for managing security parameter state for data channel packets
+ * @{ */
+
+/**
+ * Inspect an incoming packet for which no VPN tunnel is active, and
+ * determine whether a new VPN tunnel should be created.
+ * @ingroup data_crypto
+ *
+ * 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.
+ *
+ * @param tas - The standalone TLS authentication setting structure for
+ * this process.
+ * @param from - The source address of the packet.
+ * @param buf - A buffer structure containing the incoming packet.
+ *
+ * @return
+ * @li True if the packet is valid and a new VPN tunnel should be created
+ * for this client.
+ * @li False if the packet is not valid, did not pass the HMAC firewall
+ * test, or some other error occurred.
+ */
bool tls_pre_decrypt_lite (const struct tls_auth_standalone *tas,
const struct link_socket_actual *from,
const struct buffer *buf);
+
+/**
+ * Choose the appropriate security parameters with which to process an
+ * outgoing packet.
+ * @ingroup data_crypto
+ *
+ * If no appropriate security parameters can be found, or if some other
+ * error occurs, then the buffer is set to empty.
+ *
+ * @param multi - The TLS state for this packet's destination VPN tunnel.
+ * @param buf - The buffer containing the outgoing packet.
+ * @param opt - The crypto options structure into which the appropriate
+ * security parameters should be loaded.
+ */
void tls_pre_encrypt (struct tls_multi *multi,
struct buffer *buf, struct crypto_options *opt);
+
+/**
+ * Prepend the one-byte OpenVPN header to the packet, and perform some
+ * accounting for the key state used.
+ * @ingroup data_crypto
+ *
+ * @param multi - The TLS state for this packet's destination VPN tunnel.
+ * @param buf - The buffer containing the outgoing packet.
+ */
void tls_post_encrypt (struct tls_multi *multi, struct buffer *buf);
+/** @} name Functions for managing security parameter state for data channel packets */
+
+
void show_available_tls_ciphers (void);
void get_highest_preference_tls_cipher (char *buf, int size);