summaryrefslogtreecommitdiff
path: root/src/openvpn/ssl.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/openvpn/ssl.h')
-rw-r--r--src/openvpn/ssl.h507
1 files changed, 507 insertions, 0 deletions
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
new file mode 100644
index 0000000..cd7cae2
--- /dev/null
+++ b/src/openvpn/ssl.h
@@ -0,0 +1,507 @@
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ * Copyright (C) 2010 Fox Crypto B.V. <openvpn@fox-it.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * @file Control Channel SSL/Data channel negotiation module
+ */
+
+#ifndef OPENVPN_SSL_H
+#define OPENVPN_SSL_H
+
+#if defined(ENABLE_CRYPTO) && defined(ENABLE_SSL)
+
+#include "basic.h"
+#include "common.h"
+#include "crypto.h"
+#include "packet_id.h"
+#include "session_id.h"
+#include "reliable.h"
+#include "socket.h"
+#include "mtu.h"
+#include "options.h"
+#include "plugin.h"
+
+#include "ssl_common.h"
+#include "ssl_verify.h"
+#include "ssl_backend.h"
+
+/* Used in the TLS PRF function */
+#define KEY_EXPANSION_ID "OpenVPN"
+
+/* packet opcode (high 5 bits) and key-id (low 3 bits) are combined in one byte */
+#define P_KEY_ID_MASK 0x07
+#define P_OPCODE_SHIFT 3
+
+/* packet opcodes -- the V1 is intended to allow protocol changes in the future */
+#define P_CONTROL_HARD_RESET_CLIENT_V1 1 /* initial key from client, forget previous state */
+#define P_CONTROL_HARD_RESET_SERVER_V1 2 /* initial key from server, forget previous state */
+#define P_CONTROL_SOFT_RESET_V1 3 /* new key, graceful transition from old to new key */
+#define P_CONTROL_V1 4 /* control channel packet (usually TLS ciphertext) */
+#define P_ACK_V1 5 /* acknowledgement for packets received */
+#define P_DATA_V1 6 /* data channel packet */
+
+/* indicates key_method >= 2 */
+#define P_CONTROL_HARD_RESET_CLIENT_V2 7 /* initial key from client, forget previous state */
+#define P_CONTROL_HARD_RESET_SERVER_V2 8 /* initial key from server, forget previous state */
+
+/* define the range of legal opcodes */
+#define P_FIRST_OPCODE 1
+#define P_LAST_OPCODE 8
+
+/* Should we aggregate TLS
+ * acknowledgements, and tack them onto
+ * control packets? */
+#define TLS_AGGREGATE_ACK
+
+/*
+ * If TLS_AGGREGATE_ACK, set the
+ * max number of acknowledgments that
+ * can "hitch a ride" on an outgoing
+ * non-P_ACK_V1 control packet.
+ */
+#define CONTROL_SEND_ACK_MAX 4
+
+/*
+ * Define number of buffers for send and receive in the reliability layer.
+ */
+#define TLS_RELIABLE_N_SEND_BUFFERS 4 /* also window size for reliablity layer */
+#define TLS_RELIABLE_N_REC_BUFFERS 8
+
+/*
+ * Various timeouts
+ */
+#define TLS_MULTI_REFRESH 15 /* call tls_multi_process once every n seconds */
+#define TLS_MULTI_HORIZON 2 /* call tls_multi_process frequently for n seconds after
+ every packet sent/received action */
+
+/*
+ * The SSL/TLS worker thread will wait at most this many seconds for the
+ * interprocess communication pipe to the main thread to be ready to accept
+ * writes.
+ */
+#define TLS_MULTI_THREAD_SEND_TIMEOUT 5
+
+/* Interval that tls_multi_process should call tls_authentication_status */
+#define TLS_MULTI_AUTH_STATUS_INTERVAL 10
+
+/*
+ * Buffer sizes (also see mtu.h).
+ */
+
+/* Maximum length of OCC options string passed as part of auth handshake */
+#define TLS_OPTIONS_LEN 512
+
+/* Default field in X509 to be username */
+#define X509_USERNAME_FIELD_DEFAULT "CN"
+
+/*
+ * Range of key exchange methods
+ */
+#define KEY_METHOD_MIN 1
+#define KEY_METHOD_MAX 2
+
+/* key method taken from lower 4 bits */
+#define KEY_METHOD_MASK 0x0F
+
+/*
+ * Measure success rate of TLS handshakes, for debugging only
+ */
+/* #define MEASURE_TLS_HANDSHAKE_STATS */
+
+/*
+ * Used in --mode server mode to check tls-auth signature on initial
+ * packets received from new clients.
+ */
+struct tls_auth_standalone
+{
+ struct key_ctx_bi tls_auth_key;
+ struct crypto_options tls_auth_options;
+ struct frame frame;
+};
+
+/*
+ * Prepare the SSL library for use
+ */
+void init_ssl_lib (void);
+
+/*
+ * Free any internal state that the SSL library might have
+ */
+void free_ssl_lib (void);
+
+/**
+ * Build master SSL context object that serves for the whole of OpenVPN
+ * instantiation
+ */
+void init_ssl (const struct options *options, struct tls_root_ctx *ctx);
+
+/** @addtogroup control_processor
+ * @{ */
+
+/** @name Functions for initialization and cleanup of tls_multi structures
+ * @{ */
+
+/**
+ * Allocate and initialize a \c tls_multi structure.
+ * @ingroup control_processor
+ *
+ * This function allocates a new \c tls_multi structure, and performs some
+ * amount of initialization. Afterwards, the \c tls_multi_init_finalize()
+ * function must be called to finalize the structure's initialization
+ * process.
+ *
+ * @param tls_options - The configuration options to be used for this VPN
+ * tunnel.
+ *
+ * @return A newly allocated and initialized \c tls_multi structure.
+ */
+struct tls_multi *tls_multi_init (struct tls_options *tls_options);
+
+/**
+ * Finalize initialization of a \c tls_multi structure.
+ * @ingroup control_processor
+ *
+ * This function initializes the \c TM_ACTIVE \c tls_session, and in
+ * server mode also the \c TM_UNTRUSTED \c tls_session, associated with
+ * this \c tls_multi structure. It also configures the control channel's
+ * \c frame structure based on the data channel's \c frame given in
+ * argument \a frame.
+ *
+ * @param multi - The \c tls_multi structure of which to finalize
+ * initialization.
+ * @param frame - The data channel's \c frame structure.
+ */
+void tls_multi_init_finalize(struct tls_multi *multi,
+ const struct frame *frame);
+
+/*
+ * Initialize a standalone tls-auth verification object.
+ */
+struct tls_auth_standalone *tls_auth_standalone_init (struct tls_options *tls_options,
+ struct gc_arena *gc);
+
+/*
+ * Finalize a standalone tls-auth verification object.
+ */
+void tls_auth_standalone_finalize (struct tls_auth_standalone *tas,
+ const struct frame *frame);
+
+/*
+ * Set local and remote option compatibility strings.
+ * Used to verify compatibility of local and remote option
+ * sets.
+ */
+void tls_multi_init_set_options(struct tls_multi* multi,
+ const char *local,
+ const char *remote);
+
+/**
+ * Cleanup a \c tls_multi structure and free associated memory
+ * allocations.
+ * @ingroup control_processor
+ *
+ * This function cleans up a \c tls_multi structure. This includes
+ * cleaning up all associated \c tls_session structures.
+ *
+ * @param multi - The \c tls_multi structure to clean up in free.
+ * @param clear - Whether the memory allocated for the \a multi
+ * object should be overwritten with 0s.
+ */
+void tls_multi_free (struct tls_multi *multi, bool clear);
+
+/** @} name Functions for initialization and cleanup of tls_multi structures */
+
+/** @} addtogroup control_processor */
+
+#define TLSMP_INACTIVE 0
+#define TLSMP_ACTIVE 1
+#define TLSMP_KILL 2
+
+/*
+ * Called by the top-level event loop.
+ *
+ * Basically decides if we should call tls_process for
+ * the active or untrusted sessions.
+ */
+int tls_multi_process (struct tls_multi *multi,
+ struct buffer *to_link,
+ struct link_socket_actual **to_link_addr,
+ struct link_socket_info *to_link_socket_info,
+ interval_t *wakeup);
+
+
+/**************************************************************************/
+/**
+ * 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 */
+
+/*
+ * Setup private key file password. If auth_file is given, use the
+ * credentials stored in the file.
+ */
+void pem_password_setup (const char *auth_file);
+
+/*
+ * Setup authentication username and password. If auth_file is given, use the
+ * credentials stored in the file.
+ */
+void auth_user_pass_setup (const char *auth_file, const struct static_challenge_info *sc_info);
+
+/*
+ * Ensure that no caching is performed on authentication information
+ */
+void ssl_set_auth_nocache (void);
+
+/*
+ * Purge any stored authentication information, both for key files and tunnel
+ * authentication. If PCKS #11 is enabled, purge authentication for that too.
+ */
+void ssl_purge_auth (const bool auth_user_pass_only);
+
+void ssl_set_auth_token (const char *token);
+
+#ifdef ENABLE_CLIENT_CR
+/*
+ * ssl_get_auth_challenge will parse the server-pushed auth-failed
+ * reason string and return a dynamically allocated
+ * auth_challenge_info struct.
+ */
+void ssl_purge_auth_challenge (void);
+void ssl_put_auth_challenge (const char *cr_str);
+#endif
+
+/*
+ * Reserve any extra space required on frames.
+ */
+void tls_adjust_frame_parameters(struct frame *frame);
+
+/*
+ * Send a payload over the TLS control channel
+ */
+bool tls_send_payload (struct tls_multi *multi,
+ const uint8_t *data,
+ int size);
+
+/*
+ * Receive a payload through the TLS control channel
+ */
+bool tls_rec_payload (struct tls_multi *multi,
+ struct buffer *buf);
+
+#ifdef MANAGEMENT_DEF_AUTH
+static inline char *
+tls_get_peer_info(const struct tls_multi *multi)
+{
+ return multi->peer_info;
+}
+#endif
+
+/*
+ * inline functions
+ */
+
+static inline bool
+tls_initial_packet_received (const struct tls_multi *multi)
+{
+ return multi->n_sessions > 0;
+}
+
+static inline bool
+tls_test_auth_deferred_interval (const struct tls_multi *multi)
+{
+ if (multi)
+ {
+ const struct key_state *ks = &multi->session[TM_ACTIVE].key[KS_PRIMARY];
+ return now < ks->auth_deferred_expire;
+ }
+ return false;
+}
+
+static inline int
+tls_test_payload_len (const struct tls_multi *multi)
+{
+ if (multi)
+ {
+ const struct key_state *ks = &multi->session[TM_ACTIVE].key[KS_PRIMARY];
+ if (ks->state >= S_ACTIVE)
+ return BLEN (&ks->plaintext_read_buf);
+ }
+ return 0;
+}
+
+static inline void
+tls_set_single_session (struct tls_multi *multi)
+{
+ if (multi)
+ multi->opt.single_session = true;
+}
+
+/*
+ * protocol_dump() flags
+ */
+#define PD_TLS_AUTH_HMAC_SIZE_MASK 0xFF
+#define PD_SHOW_DATA (1<<8)
+#define PD_TLS (1<<9)
+#define PD_VERBOSE (1<<10)
+
+const char *protocol_dump (struct buffer *buffer,
+ unsigned int flags,
+ struct gc_arena *gc);
+
+/*
+ * debugging code
+ */
+
+#ifdef MEASURE_TLS_HANDSHAKE_STATS
+void show_tls_performance_stats(void);
+#endif
+
+/*#define EXTRACT_X509_FIELD_TEST*/
+void extract_x509_field_test (void);
+
+#endif /* ENABLE_CRYPTO && ENABLE_SSL */
+
+#endif