ASSERT(cipher_ctx_reset(ctx->cipher, iv));
}
- /* Reserve space for authentication tag */
- mac_out = buf_write_alloc(&work, mac_len);
- ASSERT(mac_out);
-
dmsg(D_PACKET_CONTENT, "ENCRYPT FROM: %s", format_hex(BPTR(buf), BLEN(buf), 80, &gc));
/* Buffer overflow check */
- if (!buf_safe(&work, buf->len + cipher_ctx_block_size(ctx->cipher)))
+ if (!buf_safe(&work, buf->len + mac_len + cipher_ctx_block_size(ctx->cipher)))
{
msg(D_CRYPT_ERRORS,
"ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d",
}
/* For AEAD ciphers, authenticate Additional Data, including opcode */
- ASSERT(cipher_ctx_update_ad(ctx->cipher, BPTR(&work), BLEN(&work) - mac_len));
+ ASSERT(cipher_ctx_update_ad(ctx->cipher, BPTR(&work), BLEN(&work)));
dmsg(D_PACKET_CONTENT, "ENCRYPT AD: %s",
- format_hex(BPTR(&work), BLEN(&work) - mac_len, 0, &gc));
+ format_hex(BPTR(&work), BLEN(&work), 0, &gc));
+
+ if (!(opt->flags & CO_AEAD_TAG_AT_THE_END))
+ {
+ /* Reserve space for authentication tag */
+ mac_out = buf_write_alloc(&work, mac_len);
+ ASSERT(mac_out);
+ }
/* Encrypt packet ID, payload */
ASSERT(cipher_ctx_update(ctx->cipher, BEND(&work), &outlen, BPTR(buf), BLEN(buf)));
ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen));
ASSERT(buf_inc_len(&work, outlen));
+ /* if the tag is at end the end, allocate it now */
+ if (opt->flags & CO_AEAD_TAG_AT_THE_END)
+ {
+ /* Reserve space for authentication tag */
+ mac_out = buf_write_alloc(&work, mac_len);
+ ASSERT(mac_out);
+ }
+
/* Write authentication tag */
ASSERT(cipher_ctx_get_tag(ctx->cipher, mac_out, mac_len));
static const char error_prefix[] = "AEAD Decrypt error";
struct packet_id_net pin = { 0 };
const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;
- uint8_t *tag_ptr = NULL;
int outlen;
struct gc_arena gc;
/* keep the tag value to feed in later */
const int tag_size = OPENVPN_AEAD_TAG_LENGTH;
- if (buf->len < tag_size)
+ if (buf->len < tag_size + 1)
{
- CRYPT_ERROR("missing tag");
+ CRYPT_ERROR("missing tag or no payload");
}
- tag_ptr = BPTR(buf);
- ASSERT(buf_advance(buf, tag_size));
- dmsg(D_PACKET_CONTENT, "DECRYPT MAC: %s", format_hex(tag_ptr, tag_size, 0, &gc));
- if (buf->len < 1)
+ const int ad_size = BPTR(buf) - ad_start;
+
+ uint8_t *tag_ptr = NULL;
+ int data_len = 0;
+
+ if (opt->flags & CO_AEAD_TAG_AT_THE_END)
+ {
+ data_len = BLEN(buf) - tag_size;
+ tag_ptr = BPTR(buf) + data_len;
+ }
+ else
{
- CRYPT_ERROR("missing payload");
+ tag_ptr = BPTR(buf);
+ ASSERT(buf_advance(buf, tag_size));
+ data_len = BLEN(buf);
}
+ dmsg(D_PACKET_CONTENT, "DECRYPT MAC: %s", format_hex(tag_ptr, tag_size, 0, &gc));
dmsg(D_PACKET_CONTENT, "DECRYPT FROM: %s", format_hex(BPTR(buf), BLEN(buf), 0, &gc));
/* Buffer overflow check (should never fail) */
CRYPT_ERROR("potential buffer overflow");
}
- {
- /* feed in tag and the authenticated data */
- const int ad_size = BPTR(buf) - ad_start - tag_size;
- ASSERT(cipher_ctx_update_ad(ctx->cipher, ad_start, ad_size));
- dmsg(D_PACKET_CONTENT, "DECRYPT AD: %s",
- format_hex(BPTR(buf) - ad_size - tag_size, ad_size, 0, &gc));
- }
+
+ /* feed in tag and the authenticated data */
+ ASSERT(cipher_ctx_update_ad(ctx->cipher, ad_start, ad_size));
+ dmsg(D_PACKET_CONTENT, "DECRYPT AD: %s",
+ format_hex(ad_start, ad_size, 0, &gc));
/* Decrypt and authenticate packet */
if (!cipher_ctx_update(ctx->cipher, BPTR(&work), &outlen, BPTR(buf),
- BLEN(buf)))
+ data_len))
{
CRYPT_ERROR("cipher update failed");
}
+
ASSERT(buf_inc_len(&work, outlen));
if (!cipher_ctx_final_check_tag(ctx->cipher, BPTR(&work) + outlen,
&outlen, tag_ptr, tag_size))
}
+/* This adds a few more methods than strictly necessary but this allows
+ * us to see which exact test was run from the backtrace of the test
+ * when it fails */
+static void
+run_data_channel_with_cipher_end(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_cipher(const char *cipher, const char *auth)
uninit_crypto_options(&co);
}
+
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");
}
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");
}
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");
}
skip();
return;
}
+
+ run_data_channel_with_cipher_end("ChaCha20-Poly1305");
run_data_channel_with_cipher("ChaCha20-Poly1305", "none");
}