aboutsummaryrefslogtreecommitdiff
path: root/src/openvpn/ssl.h
diff options
context:
space:
mode:
authorSteffan Karger2015-10-24 16:44:09 +0200
committerGert Doering2016-02-15 20:19:19 +0100
commit66407e11c4746e564bd4285e9c1a1805ecfd82bd (patch)
tree70b85495bc52ab8011a33699677fa421113d0aa2 /src/openvpn/ssl.h
parent5f5229e41d134b659e502bb2597c711aedaf8096 (diff)
downloadopenvpn-66407e11c4746e564bd4285e9c1a1805ecfd82bd.zip
openvpn-66407e11c4746e564bd4285e9c1a1805ecfd82bd.tar.gz
Add AEAD cipher support (GCM)
Add Authenticated Encryption with Additional Data (AEAD) support for ciphers, which removes the need for a separate HMAC step. The MAC is integrated into the cipher and the MAC tag is prepended to the payload. This patch is inspired by the patch originally submitted by Kenny Root on the openvpn-devel mailinglist, but does a number things differently: * Don't support XTS (makes no sense for VPN) * Don't support CCM (needs extra code to make it actually work) * Don't force the user to specify "auth none" (that would break tls-auth) * Add support for PolarSSL (and change internal API for this) * Update openvpn frame size ('link mtu') calculation for AEAD modes * Use the HMAC key as an implicit part of the IV to save 8 bytes per data channel network packet. * Also authenticate the opcode/peer-id as AD in P_DATA_V2 packets. By using the negotiated HMAC key as an implicit part of the IV for AEAD-mode ciphers in TLS mode, we can save (at least) 8 bytes on each packet sent. This is particularly interesting for connections which transfer many small packets, such as remote desktop or voip connections. The current AEAD-mode ciphers (for now GCM) are based on CTR-mode cipher operation, which requires the IV to be unique (but does not require unpredictability). IV uniqueness is guaranteed by using a combination of at least 64-bits of the HMAC key (unique per TLS session), and a 32-bit packet counter. The last 32-bit word of the 128-bit cipher block is not part of the IV, but is used as a block counter. AEAD cipher mode is not available for static key mode, since IV uniqueness is harder the guarantee over sessions, and I believe supporting AEAD in static key mode too is not worth the extra complexity. Modern setups should simply use TLS mode. OpenSSL 1.0.1-1.0.1c will not work with AEAD mode, because those versions have an unnecessary check that fails to update the cipher if the tag was not already set. 1.0.1d, which fixes that, was released in February 2013. People should have updated, and distros should have backported the fix by now. Changes in v2: * Remove extra code that was just for making OpenSSL 1.0.1-1.0.1c work in AEAD mode. * Do not make AEAD support configurable in ./configure. * Get rid of '12' magic constant in openvpn_encrypt_aead(). * Update manpage to explain that --auth is ignored for the data channel when using an AEAD cipher. * Move setting the IV in AEAD cipher modes to the IV generation code. This is a more natural place and now we can pull iv[] into the IV generation scope. * Read packet ID directly from packet buffer instead of from iv buffer, to remove the need for an extra buffer. Signed-off-by: Steffan Karger <steffan@karger.me> Acked-by: Arne Schwabe <arne@rfc2549.org> Message-Id: <CAA1AbxL_S4umZr5Nd0VTvUvXEHjoWmji18GqM6FgmWqntOKqaA@mail.gmail.com> URL: http://article.gmane.org/gmane.network.openvpn.devel/11162 Signed-off-by: Gert Doering <gert@greenie.muc.de>
Diffstat (limited to 'src/openvpn/ssl.h')
-rw-r--r--src/openvpn/ssl.h42
1 files changed, 39 insertions, 3 deletions
diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
index 20991cc..d9ff8d0 100644
--- a/src/openvpn/ssl.h
+++ b/src/openvpn/ssl.h
@@ -294,6 +294,8 @@ int tls_multi_process (struct tls_multi *multi,
* @param buf - A buffer structure containing the incoming packet.
* @param opt - Returns a crypto options structure with the appropriate security
* parameters to handle the packet if it is a data channel packet.
+ * @param ad_start - Returns a pointer to the start of the authenticated data of
+ * of this packet
*
* @return
* @li True if the packet is a control channel packet that has been
@@ -305,7 +307,8 @@ bool tls_pre_decrypt (struct tls_multi *multi,
const struct link_socket_actual *from,
struct buffer *buf,
struct crypto_options **opt,
- bool floated);
+ bool floated,
+ const uint8_t **ad_start);
/**************************************************************************/
@@ -366,8 +369,41 @@ void tls_pre_encrypt (struct tls_multi *multi,
/**
- * Prepend the one-byte OpenVPN header to the packet, and perform some
- * accounting for the key state used.
+ * 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.
+ *
+ * @param multi - The TLS state for this packet's destination VPN tunnel.
+ * @param buf - The buffer to write the header to.
+ *
+ * @ingroup data_crypto
+ */
+void
+tls_prepend_opcode_v1 (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.
+ *
+ * @param multi - The TLS state for this packet's destination VPN tunnel.
+ * @param buf - The buffer to write the header to.
+ *
+ * @ingroup data_crypto
+ */
+void
+tls_prepend_opcode_v2 (const struct tls_multi *multi, struct buffer *buf);
+
+/**
+ * Perform some accounting for the key state used.
* @ingroup data_crypto
*
* @param multi - The TLS state for this packet's destination VPN tunnel.