summaryrefslogtreecommitdiff
path: root/src/openvpn/tls_crypt.c
diff options
context:
space:
mode:
authorAlberto Gonzalez Iniesta <agi@inittab.org>2016-12-27 18:25:47 +0100
committerAlberto Gonzalez Iniesta <agi@inittab.org>2016-12-27 18:25:47 +0100
commit3a2bbdb05ca6a6996e424c9fb225cb0d53804125 (patch)
treef29063da5bec4caf3853d49a22a09c8619eebd21 /src/openvpn/tls_crypt.c
parentd53dba59e78da865c4fe820386ff2f4f76925f3b (diff)
New upstream version 2.4.0upstream/2.4.0
Diffstat (limited to 'src/openvpn/tls_crypt.c')
-rw-r--r--src/openvpn/tls_crypt.c339
1 files changed, 170 insertions, 169 deletions
diff --git a/src/openvpn/tls_crypt.c b/src/openvpn/tls_crypt.c
index d40532e..c227b09 100644
--- a/src/openvpn/tls_crypt.c
+++ b/src/openvpn/tls_crypt.c
@@ -5,7 +5,7 @@
* packet encryption, packet authentication, and
* packet compression.
*
- * Copyright (C) 2016 Fox Crypto B.V. <openvpn@fox-it.com>
+ * Copyright (C) 2016-2017 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
@@ -36,219 +36,220 @@
#include "tls_crypt.h"
-int tls_crypt_buf_overhead(void)
+int
+tls_crypt_buf_overhead(void)
{
- return packet_id_size (true) + TLS_CRYPT_TAG_SIZE + TLS_CRYPT_BLOCK_SIZE;
+ return packet_id_size(true) + TLS_CRYPT_TAG_SIZE + TLS_CRYPT_BLOCK_SIZE;
}
void
-tls_crypt_init_key (struct key_ctx_bi *key, const char *key_file,
- const char *key_inline, bool tls_server) {
- const int key_direction = tls_server ?
- KEY_DIRECTION_NORMAL : KEY_DIRECTION_INVERSE;
-
- struct key_type kt;
- kt.cipher = cipher_kt_get ("AES-256-CTR");
- kt.cipher_length = cipher_kt_key_size (kt.cipher);
- kt.digest = md_kt_get ("SHA256");
- kt.hmac_length = md_kt_size (kt.digest);
-
- if (!kt.cipher)
+tls_crypt_init_key(struct key_ctx_bi *key, const char *key_file,
+ const char *key_inline, bool tls_server) {
+ const int key_direction = tls_server ?
+ KEY_DIRECTION_NORMAL : KEY_DIRECTION_INVERSE;
+
+ struct key_type kt;
+ kt.cipher = cipher_kt_get("AES-256-CTR");
+ kt.cipher_length = cipher_kt_key_size(kt.cipher);
+ kt.digest = md_kt_get("SHA256");
+ kt.hmac_length = md_kt_size(kt.digest);
+
+ if (!kt.cipher)
{
- msg (M_FATAL, "ERROR: --tls-crypt requires AES-256-CTR support.");
+ msg(M_FATAL, "ERROR: --tls-crypt requires AES-256-CTR support.");
}
- if (!kt.digest)
+ if (!kt.digest)
{
- msg (M_FATAL, "ERROR: --tls-crypt requires HMAC-SHA-256 support.");
+ msg(M_FATAL, "ERROR: --tls-crypt requires HMAC-SHA-256 support.");
}
- crypto_read_openvpn_key (&kt, key, key_file, key_inline, key_direction,
- "Control Channel Encryption", "tls-crypt");
+ crypto_read_openvpn_key(&kt, key, key_file, key_inline, key_direction,
+ "Control Channel Encryption", "tls-crypt");
}
void
tls_crypt_adjust_frame_parameters(struct frame *frame)
{
- frame_add_to_extra_frame (frame, tls_crypt_buf_overhead());
+ frame_add_to_extra_frame(frame, tls_crypt_buf_overhead());
- msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for tls-crypt by %i bytes",
- __func__, tls_crypt_buf_overhead());
+ msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for tls-crypt by %i bytes",
+ __func__, tls_crypt_buf_overhead());
}
bool
-tls_crypt_wrap (const struct buffer *src, struct buffer *dst,
- struct crypto_options *opt) {
- const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt;
- struct gc_arena gc;
-
- /* IV, packet-ID and implicit IV required for this mode. */
- ASSERT (ctx->cipher);
- ASSERT (ctx->hmac);
- ASSERT (packet_id_initialized(&opt->packet_id));
- ASSERT (hmac_ctx_size(ctx->hmac) == 256/8);
-
- gc_init (&gc);
-
- dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP FROM: %s",
- format_hex (BPTR (src), BLEN (src), 80, &gc));
-
- /* Get packet ID */
- {
- struct packet_id_net pin;
- packet_id_alloc_outgoing (&opt->packet_id.send, &pin, true);
- packet_id_write (&pin, dst, true, false);
- }
-
- dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP AD: %s",
- format_hex (BPTR (dst), BLEN (dst), 0, &gc));
-
- /* Buffer overflow check */
- if (!buf_safe (dst, BLEN (src) + TLS_CRYPT_BLOCK_SIZE + TLS_CRYPT_TAG_SIZE))
+tls_crypt_wrap(const struct buffer *src, struct buffer *dst,
+ struct crypto_options *opt) {
+ const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt;
+ struct gc_arena gc;
+
+ /* IV, packet-ID and implicit IV required for this mode. */
+ ASSERT(ctx->cipher);
+ ASSERT(ctx->hmac);
+ ASSERT(packet_id_initialized(&opt->packet_id));
+ ASSERT(hmac_ctx_size(ctx->hmac) == 256/8);
+
+ gc_init(&gc);
+
+ dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP FROM: %s",
+ format_hex(BPTR(src), BLEN(src), 80, &gc));
+
+ /* Get packet ID */
{
- msg (D_CRYPT_ERRORS, "TLS-CRYPT WRAP: buffer size error, "
- "sc=%d so=%d sl=%d dc=%d do=%d dl=%d", src->capacity, src->offset,
- src->len, dst->capacity, dst->offset, dst->len);
- goto err;
+ struct packet_id_net pin;
+ packet_id_alloc_outgoing(&opt->packet_id.send, &pin, true);
+ packet_id_write(&pin, dst, true, false);
}
- /* Calculate auth tag and synthetic IV */
- {
- uint8_t *tag = NULL;
- hmac_ctx_reset (ctx->hmac);
- hmac_ctx_update (ctx->hmac, BPTR (dst), BLEN (dst));
- hmac_ctx_update (ctx->hmac, BPTR (src), BLEN (src));
+ dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP AD: %s",
+ format_hex(BPTR(dst), BLEN(dst), 0, &gc));
+
+ /* Buffer overflow check */
+ if (!buf_safe(dst, BLEN(src) + TLS_CRYPT_BLOCK_SIZE + TLS_CRYPT_TAG_SIZE))
+ {
+ msg(D_CRYPT_ERRORS, "TLS-CRYPT WRAP: buffer size error, "
+ "sc=%d so=%d sl=%d dc=%d do=%d dl=%d", src->capacity, src->offset,
+ src->len, dst->capacity, dst->offset, dst->len);
+ goto err;
+ }
+
+ /* Calculate auth tag and synthetic IV */
+ {
+ uint8_t *tag = NULL;
+ hmac_ctx_reset(ctx->hmac);
+ hmac_ctx_update(ctx->hmac, BPTR(dst), BLEN(dst));
+ hmac_ctx_update(ctx->hmac, BPTR(src), BLEN(src));
- ASSERT (tag = buf_write_alloc (dst, TLS_CRYPT_TAG_SIZE));
- hmac_ctx_final (ctx->hmac, tag);
+ ASSERT(tag = buf_write_alloc(dst, TLS_CRYPT_TAG_SIZE));
+ hmac_ctx_final(ctx->hmac, tag);
- dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP TAG: %s",
- format_hex (tag, TLS_CRYPT_TAG_SIZE, 0, &gc));
+ dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP TAG: %s",
+ format_hex(tag, TLS_CRYPT_TAG_SIZE, 0, &gc));
- /* Use the 128 most significant bits of the tag as IV */
- ASSERT (cipher_ctx_reset (ctx->cipher, tag));
- }
+ /* Use the 128 most significant bits of the tag as IV */
+ ASSERT(cipher_ctx_reset(ctx->cipher, tag));
+ }
- /* Encrypt src */
- {
- int outlen = 0;
- ASSERT (cipher_ctx_update (ctx->cipher, BEND (dst), &outlen,
- BPTR (src), BLEN(src)));
- ASSERT (buf_inc_len (dst, outlen));
- ASSERT (cipher_ctx_final (ctx->cipher, BPTR (dst), &outlen));
- ASSERT (buf_inc_len (dst, outlen));
- }
+ /* Encrypt src */
+ {
+ int outlen = 0;
+ ASSERT(cipher_ctx_update(ctx->cipher, BEND(dst), &outlen,
+ BPTR(src), BLEN(src)));
+ ASSERT(buf_inc_len(dst, outlen));
+ ASSERT(cipher_ctx_final(ctx->cipher, BPTR(dst), &outlen));
+ ASSERT(buf_inc_len(dst, outlen));
+ }
- dmsg (D_PACKET_CONTENT, "TLS-CRYPT WRAP TO: %s",
- format_hex (BPTR (dst), BLEN (dst), 80, &gc));
+ dmsg(D_PACKET_CONTENT, "TLS-CRYPT WRAP TO: %s",
+ format_hex(BPTR(dst), BLEN(dst), 80, &gc));
- gc_free (&gc);
- return true;
+ gc_free(&gc);
+ return true;
err:
- crypto_clear_error();
- dst->len = 0;
- gc_free (&gc);
- return false;
+ crypto_clear_error();
+ dst->len = 0;
+ gc_free(&gc);
+ return false;
}
bool
-tls_crypt_unwrap (const struct buffer *src, struct buffer *dst,
- struct crypto_options *opt)
+tls_crypt_unwrap(const struct buffer *src, struct buffer *dst,
+ struct crypto_options *opt)
{
- static const char error_prefix[] = "tls-crypt unwrap error";
- const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;
- struct gc_arena gc;
+ static const char error_prefix[] = "tls-crypt unwrap error";
+ const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;
+ struct gc_arena gc;
- gc_init (&gc);
+ gc_init(&gc);
- ASSERT (opt);
- ASSERT (src->len > 0);
- ASSERT (ctx->cipher);
- ASSERT (packet_id_initialized (&opt->packet_id) ||
- (opt->flags & CO_IGNORE_PACKET_ID));
+ ASSERT(opt);
+ ASSERT(src->len > 0);
+ ASSERT(ctx->cipher);
+ ASSERT(packet_id_initialized(&opt->packet_id)
+ || (opt->flags & CO_IGNORE_PACKET_ID));
- dmsg (D_PACKET_CONTENT, "TLS-CRYPT UNWRAP FROM: %s",
- format_hex (BPTR (src), BLEN (src), 80, &gc));
+ dmsg(D_PACKET_CONTENT, "TLS-CRYPT UNWRAP FROM: %s",
+ format_hex(BPTR(src), BLEN(src), 80, &gc));
+
+ if (buf_len(src) < TLS_CRYPT_OFF_CT)
+ {
+ CRYPT_ERROR("packet too short");
+ }
+
+ /* Decrypt cipher text */
+ {
+ int outlen = 0;
+
+ /* Buffer overflow check (should never fail) */
+ if (!buf_safe(dst, BLEN(src) - TLS_CRYPT_OFF_CT + TLS_CRYPT_BLOCK_SIZE))
+ {
+ CRYPT_ERROR("potential buffer overflow");
+ }
+
+ if (!cipher_ctx_reset(ctx->cipher, BPTR(src) + TLS_CRYPT_OFF_TAG))
+ {
+ CRYPT_ERROR("cipher reset failed");
+ }
+ if (!cipher_ctx_update(ctx->cipher, BPTR(dst), &outlen,
+ BPTR(src) + TLS_CRYPT_OFF_CT, BLEN(src) - TLS_CRYPT_OFF_CT))
+ {
+ CRYPT_ERROR("cipher update failed");
+ }
+ ASSERT(buf_inc_len(dst, outlen));
+ if (!cipher_ctx_final(ctx->cipher, BPTR(dst), &outlen))
+ {
+ CRYPT_ERROR("cipher final failed");
+ }
+ ASSERT(buf_inc_len(dst, outlen));
+ }
- if (buf_len (src) < TLS_CRYPT_OFF_CT)
+ /* Check authentication */
{
- CRYPT_ERROR ("packet too short");
+ const uint8_t *tag = BPTR(src) + TLS_CRYPT_OFF_TAG;
+ uint8_t tag_check[TLS_CRYPT_TAG_SIZE] = { 0 };
+
+ dmsg(D_PACKET_CONTENT, "TLS-CRYPT UNWRAP AD: %s",
+ format_hex(BPTR(src), TLS_CRYPT_OFF_TAG, 0, &gc));
+ dmsg(D_PACKET_CONTENT, "TLS-CRYPT UNWRAP TO: %s",
+ format_hex(BPTR(dst), BLEN(dst), 80, &gc));
+
+ hmac_ctx_reset(ctx->hmac);
+ hmac_ctx_update(ctx->hmac, BPTR(src), TLS_CRYPT_OFF_TAG);
+ hmac_ctx_update(ctx->hmac, BPTR(dst), BLEN(dst));
+ hmac_ctx_final(ctx->hmac, tag_check);
+
+ if (memcmp_constant_time(tag, tag_check, sizeof(tag_check)))
+ {
+ dmsg(D_CRYPTO_DEBUG, "tag : %s",
+ format_hex(tag, sizeof(tag_check), 0, &gc));
+ dmsg(D_CRYPTO_DEBUG, "tag_check: %s",
+ format_hex(tag_check, sizeof(tag_check), 0, &gc));
+ CRYPT_ERROR("packet authentication failed");
+ }
}
- /* Decrypt cipher text */
- {
- int outlen = 0;
-
- /* Buffer overflow check (should never fail) */
- if (!buf_safe (dst, BLEN (src) - TLS_CRYPT_OFF_CT + TLS_CRYPT_BLOCK_SIZE))
- {
- CRYPT_ERROR ("potential buffer overflow");
- }
-
- if (!cipher_ctx_reset (ctx->cipher, BPTR (src) + TLS_CRYPT_OFF_TAG))
- {
- CRYPT_ERROR ("cipher reset failed");
- }
- if (!cipher_ctx_update (ctx->cipher, BPTR (dst), &outlen,
- BPTR (src) + TLS_CRYPT_OFF_CT, BLEN (src) - TLS_CRYPT_OFF_CT))
- {
- CRYPT_ERROR ("cipher update failed");
- }
- ASSERT (buf_inc_len (dst, outlen));
- if (!cipher_ctx_final (ctx->cipher, BPTR(dst), &outlen))
- {
- CRYPT_ERROR ("cipher final failed");
- }
- ASSERT (buf_inc_len (dst, outlen));
- }
-
- /* Check authentication */
- {
- const uint8_t *tag = BPTR (src) + TLS_CRYPT_OFF_TAG;
- uint8_t tag_check[TLS_CRYPT_TAG_SIZE] = { 0 };
-
- dmsg (D_PACKET_CONTENT, "TLS-CRYPT UNWRAP AD: %s",
- format_hex (BPTR (src), TLS_CRYPT_OFF_TAG, 0, &gc));
- dmsg (D_PACKET_CONTENT, "TLS-CRYPT UNWRAP TO: %s",
- format_hex (BPTR (dst), BLEN (dst), 80, &gc));
-
- hmac_ctx_reset (ctx->hmac);
- hmac_ctx_update (ctx->hmac, BPTR (src), TLS_CRYPT_OFF_TAG);
- hmac_ctx_update (ctx->hmac, BPTR (dst), BLEN (dst));
- hmac_ctx_final (ctx->hmac, tag_check);
-
- if (memcmp_constant_time (tag, tag_check, sizeof(tag_check)))
- {
- dmsg (D_CRYPTO_DEBUG, "tag : %s",
- format_hex (tag, sizeof(tag_check), 0, &gc));
- dmsg (D_CRYPTO_DEBUG, "tag_check: %s",
- format_hex (tag_check, sizeof(tag_check), 0, &gc));
- CRYPT_ERROR ("packet authentication failed");
- }
- }
-
- /* Check replay */
- if (!(opt->flags & CO_IGNORE_PACKET_ID))
+ /* Check replay */
+ if (!(opt->flags & CO_IGNORE_PACKET_ID))
{
- struct packet_id_net pin;
- struct buffer tmp = *src;
- ASSERT (buf_advance (&tmp, TLS_CRYPT_OFF_PID));
- ASSERT (packet_id_read (&pin, &tmp, true));
- if (!crypto_check_replay (opt, &pin, error_prefix, &gc))
- {
- CRYPT_ERROR ("packet replay");
- }
+ struct packet_id_net pin;
+ struct buffer tmp = *src;
+ ASSERT(buf_advance(&tmp, TLS_CRYPT_OFF_PID));
+ ASSERT(packet_id_read(&pin, &tmp, true));
+ if (!crypto_check_replay(opt, &pin, error_prefix, &gc))
+ {
+ CRYPT_ERROR("packet replay");
+ }
}
- gc_free (&gc);
- return true;
+ gc_free(&gc);
+ return true;
- error_exit:
- crypto_clear_error();
- dst->len = 0;
- gc_free (&gc);
- return false;
+error_exit:
+ crypto_clear_error();
+ dst->len = 0;
+ gc_free(&gc);
+ return false;
}
#endif /* EMABLE_CRYPTO */