mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-19 19:42:30 +02:00
Add unit test for encrypting/decrypting data channel
This test is reusing code from --test-crypto but is modified to not rely on the static key functionality and also only tests the most common algorithm. So it does not yet completely replace --test-crypto Change-Id: Ifa5ae96165d17b3cae4afc53e844bb34d1610e58 Acked-by: Frank Lichtenheld <frank@lichtenheld.com> Message-Id: <20240208085749.869-1-gert@greenie.muc.de> URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg28195.html Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
ca122f990c
commit
70b39f2bea
@ -44,6 +44,9 @@
|
||||
#include "ssl_verify_backend.h"
|
||||
#include "win32.h"
|
||||
#include "test_common.h"
|
||||
#include "ssl.h"
|
||||
#include "buffer.h"
|
||||
#include "packet_id.h"
|
||||
|
||||
/* Mock function to be allowed to include win32.c which is required for
|
||||
* getting the temp directory */
|
||||
@ -120,20 +123,238 @@ crypto_pem_encode_certificate(void **state)
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
static void
|
||||
init_implicit_iv(struct crypto_options *co)
|
||||
{
|
||||
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);
|
||||
ASSERT(cipher_ctx_iv_length(cipher) <= OPENVPN_MAX_IV_LENGTH);
|
||||
ASSERT(cipher_ctx_iv_length(cipher) >= OPENVPN_AEAD_MIN_IV_LEN);
|
||||
|
||||
/* Generate dummy implicit IV */
|
||||
ASSERT(rand_bytes(co->key_ctx_bi.encrypt.implicit_iv,
|
||||
OPENVPN_MAX_IV_LENGTH));
|
||||
co->key_ctx_bi.encrypt.implicit_iv_len = impl_iv_len;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
init_frame_parameters(struct frame *frame)
|
||||
{
|
||||
int overhead = 0;
|
||||
|
||||
/* tls-auth and tls-crypt */
|
||||
overhead += 128;
|
||||
|
||||
/* TCP length field and opcode */
|
||||
overhead += 3;
|
||||
|
||||
/* ACK array and remote SESSION ID (part of the ACK array) */
|
||||
overhead += ACK_SIZE(RELIABLE_ACK_SIZE);
|
||||
|
||||
/* Previous OpenVPN version calculated the maximum size and buffer of a
|
||||
* control frame depending on the overhead of the data channel frame
|
||||
* overhead and limited its maximum size to 1250. Since control frames
|
||||
* also need to fit into data channel buffer we have the same
|
||||
* default of 1500 + 100 as data channel buffers have. Increasing
|
||||
* control channel mtu beyond this limit also increases the data channel
|
||||
* buffers */
|
||||
int tls_mtu = 1500;
|
||||
frame->buf.payload_size = tls_mtu + 100;
|
||||
|
||||
frame->buf.headroom = overhead;
|
||||
frame->buf.tailroom = overhead;
|
||||
|
||||
frame->tun_mtu = tls_mtu;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
do_data_channel_round_trip(struct crypto_options *co)
|
||||
{
|
||||
struct gc_arena gc = gc_new();
|
||||
|
||||
/* initialise frame for the test */
|
||||
struct frame frame;
|
||||
init_frame_parameters(&frame);
|
||||
|
||||
struct buffer src = alloc_buf_gc(frame.buf.payload_size, &gc);
|
||||
struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
|
||||
struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
|
||||
struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
|
||||
struct buffer buf = clear_buf();
|
||||
void *buf_p;
|
||||
|
||||
/* init work */
|
||||
ASSERT(buf_init(&work, frame.buf.headroom));
|
||||
|
||||
init_implicit_iv(co);
|
||||
update_time();
|
||||
|
||||
/* Test encryption, decryption for all packet sizes */
|
||||
for (int i = 1; i <= frame.buf.payload_size; ++i)
|
||||
{
|
||||
|
||||
/* msg(M_INFO, "TESTING ENCRYPT/DECRYPT of packet length=%d", i); */
|
||||
|
||||
/*
|
||||
* Load src with random data.
|
||||
*/
|
||||
ASSERT(buf_init(&src, 0));
|
||||
ASSERT(i <= src.capacity);
|
||||
src.len = i;
|
||||
ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
|
||||
|
||||
/* copy source to input buf */
|
||||
buf = work;
|
||||
buf_p = buf_write_alloc(&buf, BLEN(&src));
|
||||
ASSERT(buf_p);
|
||||
memcpy(buf_p, BPTR(&src), BLEN(&src));
|
||||
|
||||
/* initialize work buffer with buf.headroom bytes of prepend capacity */
|
||||
ASSERT(buf_init(&encrypt_workspace, frame.buf.headroom));
|
||||
|
||||
/* encrypt */
|
||||
openvpn_encrypt(&buf, encrypt_workspace, co);
|
||||
|
||||
/* decrypt */
|
||||
openvpn_decrypt(&buf, decrypt_workspace, co, &frame, BPTR(&buf));
|
||||
|
||||
/* compare */
|
||||
assert_int_equal(buf.len, src.len);
|
||||
assert_memory_equal(BPTR(&src), BPTR(&buf), i);
|
||||
|
||||
}
|
||||
gc_free(&gc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct crypto_options
|
||||
init_crypto_options(const char *cipher, const char *auth)
|
||||
{
|
||||
struct key2 key2 = { .n = 2};
|
||||
|
||||
ASSERT(rand_bytes(key2.keys[0].cipher, sizeof(key2.keys[0].cipher)));
|
||||
ASSERT(rand_bytes(key2.keys[0].hmac, sizeof(key2.keys[0].hmac)));
|
||||
ASSERT(rand_bytes(key2.keys[1].cipher, sizeof(key2.keys[1].cipher)));
|
||||
ASSERT(rand_bytes(key2.keys[1].hmac, sizeof(key2.keys)[1].hmac));
|
||||
|
||||
struct crypto_options co = { 0 };
|
||||
|
||||
struct key_type kt = create_kt(cipher, auth, "ssl-test");
|
||||
|
||||
init_key_ctx_bi(&co.key_ctx_bi, &key2, 0, &kt, "unit-test-ssl");
|
||||
packet_id_init(&co.packet_id, 5, 5, "UNITTEST", 0);
|
||||
|
||||
return co;
|
||||
}
|
||||
|
||||
static void
|
||||
uninit_crypto_options(struct crypto_options *co)
|
||||
{
|
||||
packet_id_free(&co->packet_id);
|
||||
free_key_ctx_bi(&co->key_ctx_bi);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
run_data_channel_with_cipher(const char *cipher, const char *auth)
|
||||
{
|
||||
struct crypto_options co = init_crypto_options(cipher, auth);
|
||||
do_data_channel_round_trip(&co);
|
||||
uninit_crypto_options(&co);
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_channel_roundtrip_aes_128_gcm(void **state)
|
||||
{
|
||||
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("AES-192-GCM", "none");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_channel_roundtrip_aes_256_gcm(void **state)
|
||||
{
|
||||
run_data_channel_with_cipher("AES-256-GCM", "none");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_channel_roundtrip_aes_128_cbc(void **state)
|
||||
{
|
||||
run_data_channel_with_cipher("AES-128-CBC", "SHA256");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_channel_roundtrip_aes_192_cbc(void **state)
|
||||
{
|
||||
run_data_channel_with_cipher("AES-192-CBC", "SHA256");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_channel_roundtrip_aes_256_cbc(void **state)
|
||||
{
|
||||
run_data_channel_with_cipher("AES-256-CBC", "SHA256");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_channel_roundtrip_chacha20_poly1305(void **state)
|
||||
{
|
||||
if (!cipher_valid("ChaCha20-Poly1305"))
|
||||
{
|
||||
skip();
|
||||
return;
|
||||
}
|
||||
run_data_channel_with_cipher("ChaCha20-Poly1305", "none");
|
||||
}
|
||||
|
||||
static void
|
||||
test_data_channel_roundtrip_bf_cbc(void **state)
|
||||
{
|
||||
if (!cipher_valid("BF-CBC"))
|
||||
{
|
||||
skip();
|
||||
return;
|
||||
}
|
||||
run_data_channel_with_cipher("BF-CBC", "SHA1");
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
openvpn_unit_test_setup();
|
||||
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(crypto_pem_encode_certificate)
|
||||
cmocka_unit_test(crypto_pem_encode_certificate),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_aes_128_gcm),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_aes_192_gcm),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_aes_256_gcm),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_chacha20_poly1305),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_aes_128_cbc),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_aes_192_cbc),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_aes_256_cbc),
|
||||
cmocka_unit_test(test_data_channel_roundtrip_bf_cbc),
|
||||
};
|
||||
|
||||
#if defined(ENABLE_CRYPTO_OPENSSL)
|
||||
tls_init_lib();
|
||||
#endif
|
||||
|
||||
int ret = cmocka_run_group_tests_name("crypto tests", tests, NULL, NULL);
|
||||
int ret = cmocka_run_group_tests_name("ssl tests", tests, NULL, NULL);
|
||||
|
||||
#if defined(ENABLE_CRYPTO_OPENSSL)
|
||||
tls_free_lib();
|
||||
|
Loading…
Reference in New Issue
Block a user