@@ -68,6 +68,7 @@
const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt;
uint8_t *mac_out = NULL;
const int mac_len = OPENVPN_AEAD_TAG_LENGTH;
+ bool longiv = opt->flags & CO_64_BIT_PKT_ID;
/* IV, packet-ID and implicit IV required for this mode. */
ASSERT(ctx->cipher);
@@ -86,7 +87,7 @@
buf_set_write(&iv_buffer, iv, iv_len);
/* IV starts with packet id to make the IV unique for packet */
- if (!packet_id_write(&opt->packet_id.send, &iv_buffer, false, false))
+ if (!packet_id_write(&opt->packet_id.send, &iv_buffer, longiv, false))
{
msg(D_CRYPT_ERRORS, "ENCRYPT ERROR: packet ID roll over");
goto err;
@@ -384,6 +385,8 @@
/* IV and Packet ID required for this mode */
ASSERT(packet_id_initialized(&opt->packet_id));
+ bool longiv = opt->flags & CO_64_BIT_PKT_ID;
+
/* Combine IV from explicit part from packet and implicit part from context */
{
uint8_t iv[OPENVPN_MAX_IV_LENGTH] = { 0 };
@@ -409,7 +412,7 @@
}
/* Read packet ID from packet */
- if (!packet_id_read(&pin, buf, false))
+ if (!packet_id_read(&pin, buf, longiv))
{
CRYPT_ERROR("error reading packet-id");
}
@@ -283,6 +283,11 @@
/**< Bit-flag indicating that the AEAD tag is at the end of the
* packet.
*/
+#define CO_64_BIT_PKT_ID (1<<9)
+ /**< Bit-flag indicating that we should use a 64 bit (8 byte) packet
+ * counter instead of the 32 bit that we normally use.
+ */
+
unsigned int flags; /**< Bit-flags determining behavior of
* security operation functions. */
@@ -2327,6 +2327,10 @@
{
buf_printf(&out, " aead-tag-end");
}
+ if (o->imported_protocol_flags & CO_64_BIT_PKT_ID)
+ {
+ buf_printf(&out, " pkt-id-64-bit");
+ }
}
if (buf_len(&out) > strlen(header))
@@ -3297,6 +3301,16 @@
to.push_peer_info_detail = 1;
}
+ /* Check if the DCO drivers support the new 64bit packet counter and
+ * AEAD tag at the end */
+ if (dco_enabled(options))
+ {
+ to.data_v3_features_supported = false;
+ }
+ else
+ {
+ to.data_v3_features_supported = true;
+ }
/* should we not xmit any packets until we get an initial
* response from client? */
@@ -1851,6 +1851,13 @@
o->imported_protocol_flags |= CO_USE_CC_EXIT_NOTIFY;
}
+ if (tls_multi->session[TM_ACTIVE].opt->data_v3_features_supported
+ && (proto & IV_PROTO_DATA_V3))
+ {
+ o->imported_protocol_flags |= CO_AEAD_TAG_AT_THE_END;
+ o->imported_protocol_flags |= CO_64_BIT_PKT_ID;
+ }
+
/* Select cipher if client supports Negotiable Crypto Parameters */
/* if we have already created our key, we cannot *change* our own
@@ -8690,6 +8690,10 @@
{
options->imported_protocol_flags |= CO_AEAD_TAG_AT_THE_END;
}
+ else if (streq(p[j], "pkt-id-64-bit"))
+ {
+ options->imported_protocol_flags |= CO_64_BIT_PKT_ID;
+ }
else
{
msg(msglevel, "Unknown protocol-flags flag: %s", p[j]);
@@ -691,6 +691,10 @@
{
buf_printf(&proto_flags, " aead-tag-end");
}
+ if (o->imported_protocol_flags & CO_64_BIT_PKT_ID)
+ {
+ buf_printf(&proto_flags, " pkt-id-64-bit");
+ }
if (buf_len(&proto_flags) > 0)
{
@@ -105,9 +105,11 @@
* @param ctx Encrypt/decrypt key context
* @param key HMAC key, used to calculate implicit IV
* @param key_len HMAC key length
+ * @param long_pkt_id 64-bit packet counters are used
*/
static void
-key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len);
+key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len,
+ bool long_pkt_id);
/**
@@ -1369,13 +1371,15 @@
}
else
{
+ bool longiv = ks->crypto_options.flags & CO_64_BIT_PKT_ID;
init_key_ctx_bi(key, key2, key_direction, key_type, "Data Channel");
/* Initialize implicit IVs */
- key_ctx_update_implicit_iv(&key->encrypt, key2->keys[(int)server].hmac,
- MAX_HMAC_KEY_LENGTH);
+ key_ctx_update_implicit_iv(&key->encrypt,
+ key2->keys[(int)server].hmac,
+ MAX_HMAC_KEY_LENGTH, longiv);
key_ctx_update_implicit_iv(&key->decrypt,
key2->keys[1 - (int)server].hmac,
- MAX_HMAC_KEY_LENGTH);
+ MAX_HMAC_KEY_LENGTH, longiv);
}
}
@@ -1513,14 +1517,15 @@
}
static void
-key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key, size_t key_len)
+key_ctx_update_implicit_iv(struct key_ctx *ctx, uint8_t *key,
+ size_t key_len, bool longiv)
{
/* Only use implicit IV in AEAD cipher mode, where HMAC key is not used */
if (cipher_ctx_mode_aead(ctx->cipher))
{
size_t impl_iv_len = 0;
ASSERT(cipher_ctx_iv_length(ctx->cipher) >= OPENVPN_AEAD_MIN_IV_LEN);
- impl_iv_len = cipher_ctx_iv_length(ctx->cipher) - sizeof(packet_id_type);
+ impl_iv_len = cipher_ctx_iv_length(ctx->cipher) - packet_id_size(longiv);
ASSERT(impl_iv_len <= OPENVPN_MAX_IV_LENGTH);
ASSERT(impl_iv_len <= key_len);
memcpy(ctx->implicit_iv, key, impl_iv_len);
@@ -1935,6 +1940,12 @@
iv_proto |= IV_PROTO_DYN_TLS_CRYPT;
#endif
+ /* support for AEAD tag at the end and 8 byte IV */
+ if (session->opt->data_v3_features_supported)
+ {
+ iv_proto |= IV_PROTO_DATA_V3;
+ }
+
buf_printf(&out, "IV_PROTO=%d\n", iv_proto);
if (session->opt->push_peer_info_detail > 1)
@@ -311,7 +311,6 @@
/* from command line */
bool single_session;
- bool disable_occ;
int mode;
bool pull;
/**
@@ -361,6 +360,8 @@
const char *config_ciphername;
const char *config_ncp_ciphers;
+ bool data_v3_features_supported; /**< dco supports new data channel features */
+
bool tls_crypt_v2;
const char *tls_crypt_v2_verify_script;
@@ -490,8 +491,6 @@
*/
int key_id;
- int limit_next; /* used for traffic shaping on the control channel */
-
int verify_maxlevel;
char *common_name;
@@ -430,6 +430,12 @@
session->opt->crypto_flags |= CO_USE_CC_EXIT_NOTIFY;
}
+ if (session->opt->data_v3_features_supported && (iv_proto_peer & IV_PROTO_DATA_V3))
+ {
+ session->opt->crypto_flags |= CO_AEAD_TAG_AT_THE_END;
+ session->opt->crypto_flags |= CO_64_BIT_PKT_ID;
+ }
+
#if defined(HAVE_EXPORT_KEYING_MATERIAL)
if (iv_proto_peer & IV_PROTO_TLS_KEY_EXPORT)
{
@@ -128,9 +128,12 @@
{
cipher_ctx_t *cipher = co->key_ctx_bi.encrypt.cipher;
+
if (cipher_ctx_mode_aead(cipher))
{
- size_t impl_iv_len = cipher_ctx_iv_length(cipher) - sizeof(packet_id_type);
+ bool longiv = co->flags & CO_64_BIT_PKT_ID;
+
+ size_t impl_iv_len = cipher_ctx_iv_length(cipher) - packet_id_size(longiv);
ASSERT(cipher_ctx_iv_length(cipher) <= OPENVPN_MAX_IV_LENGTH);
ASSERT(cipher_ctx_iv_length(cipher) >= OPENVPN_AEAD_MIN_IV_LEN);
@@ -142,6 +145,11 @@
memcpy(co->key_ctx_bi.decrypt.implicit_iv,
co->key_ctx_bi.encrypt.implicit_iv, OPENVPN_MAX_IV_LENGTH);
co->key_ctx_bi.decrypt.implicit_iv_len = impl_iv_len;
+
+ if (longiv)
+ {
+ co->flags |= CO_64_BIT_PKT_ID;
+ }
}
}
@@ -280,6 +288,25 @@
}
static void
+run_data_channel_with_cipher_end_and_long_pkt_counter(const char *cipher)
+{
+ struct crypto_options co = init_crypto_options(cipher, "none");
+ co.flags |= CO_AEAD_TAG_AT_THE_END;
+ do_data_channel_round_trip(&co);
+ uninit_crypto_options(&co);
+}
+
+static void
+run_data_channel_with_long_pkt_counter(const char *cipher)
+{
+ struct crypto_options co = init_crypto_options(cipher, "none");
+ co.flags |= CO_64_BIT_PKT_ID;
+ do_data_channel_round_trip(&co);
+ uninit_crypto_options(&co);
+}
+
+
+static void
run_data_channel_with_cipher(const char *cipher, const char *auth)
{
struct crypto_options co = init_crypto_options(cipher, auth);
@@ -289,24 +316,30 @@
static void
+run_aead_channel_tests(const char *cipher)
+{
+ run_data_channel_with_cipher_end(cipher);
+ run_data_channel_with_cipher(cipher, "none");
+ run_data_channel_with_cipher_end_and_long_pkt_counter(cipher);
+ run_data_channel_with_long_pkt_counter(cipher);
+}
+
+static void
test_data_channel_roundtrip_aes_128_gcm(void **state)
{
- run_data_channel_with_cipher_end("AES-128-GCM");
- run_data_channel_with_cipher("AES-128-GCM", "none");
+ run_aead_channel_tests("AES-128-GCM");
}
static void
test_data_channel_roundtrip_aes_192_gcm(void **state)
{
- run_data_channel_with_cipher_end("AES-192-GCM");
- run_data_channel_with_cipher("AES-192-GCM", "none");
+ run_aead_channel_tests("AES-192-GCM");
}
static void
test_data_channel_roundtrip_aes_256_gcm(void **state)
{
- run_data_channel_with_cipher_end("AES-256-GCM");
- run_data_channel_with_cipher("AES-256-GCM", "none");
+ run_aead_channel_tests("AES-256-GCM");
}
static void
@@ -336,8 +369,7 @@
return;
}
- run_data_channel_with_cipher_end("ChaCha20-Poly1305");
- run_data_channel_with_cipher("ChaCha20-Poly1305", "none");
+ run_aead_channel_tests("ChaCha20-Poly1305");
}
static void