45#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
46#include <openssl/core_names.h>
47#include <openssl/kdf.h>
50static const char testtext[] =
"Dummy text to test PEM encoding";
104 for (
int i = 0;
i < strlen(ciphername);
i++)
106 upper[
i] = (char)toupper((
unsigned char)ciphername[
i]);
107 lower[
i] = (char)tolower((
unsigned char)ciphername[
i]);
110 random_case[
i] = upper[
i];
114 random_case[
i] = lower[
i];
120 openvpn_name = upper;
146static const char *
ipsumlorem =
"Lorem ipsum dolor sit amet, consectetur "
147 "adipisici elit, sed eiusmod tempor incidunt "
148 "ut labore et dolore magna aliqua.";
153 const char *seedstr =
"Quis aute iure reprehenderit in voluptate "
154 "velit esse cillum dolore";
155 const unsigned char *seed = (
const unsigned char *)seedstr;
156 const size_t seed_len = strlen(seedstr);
159 const unsigned char *secret = (
const unsigned char *)
ipsumlorem;
160 size_t secret_len = strlen((
const char *)secret);
164 bool ret =
ssl_tls1_PRF(seed, seed_len, secret, secret_len, out,
sizeof(out));
166#if defined(LIBRESSL_VERSION_NUMBER) || defined(ENABLE_CRYPTO_WOLFSSL)
171 uint8_t good_prf[32] = { 0xd9, 0x8c, 0x85, 0x18, 0xc8, 0x5e, 0x94, 0x69, 0x27, 0x91, 0x6a,
172 0xcf, 0xc2, 0xd5, 0x92, 0xfb, 0xb1, 0x56, 0x7e, 0x4b, 0x4b, 0x14,
173 0x59, 0xe6, 0xa9, 0x04, 0xac, 0x2d, 0xda, 0xb7, 0x2d, 0x67 };
174 assert_memory_equal(good_prf, out,
sizeof(out));
179static uint8_t
goodhash[20] = { 0x58, 0xea, 0x5a, 0xf0, 0x42, 0x94, 0xe9, 0x17, 0xed, 0x84,
180 0xb9, 0xf0, 0x83, 0x30, 0x23, 0xae, 0x8b, 0xa7, 0x7e, 0xb8 };
211 memset(
key, 0x55,
sizeof(
key));
230 struct frame f = { 0 };
242 assert_int_equal(linkmtu, 1400);
251 assert_int_equal(linkmtu, 1408);
257 assert_int_equal(linkmtu, 1440);
263 assert_int_equal(linkmtu, 1440);
269 assert_int_equal(linkmtu, 1444);
274 assert_int_equal(linkmtu, 1446);
283 assert_int_equal(linkmtu, 1445);
285#if defined(ENABLE_FRAGMENT)
289 assert_int_equal(linkmtu, 1449);
307 assert_int_equal(linkmtu, 1457);
313 assert_int_equal(linkmtu, 1457);
320 assert_int_equal(linkmtu, 1405);
326 assert_int_equal(linkmtu, 1449);
329#if defined(USE_COMP) && defined(ENABLE_FRAGMENT)
335 assert_int_equal(linkmtu, 1454);
340 assert_int_equal(linkmtu, 1464);
351 struct frame f = { 0 };
367 assert_int_equal(f.
mss_fix, 952);
377 assert_int_equal(f.
mss_fix, 952);
384 for (
int i = 990;
i <= 1010;
i++)
393 assert_int_equal(f.
mss_fix, 911);
397 assert_int_equal(f.
mss_fix, 943);
401 assert_int_equal(f.
mss_fix, 927);
410 for (
int i = 990;
i <= 1010;
i++)
419 assert_int_equal(f.
mss_fix, 910);
423 assert_int_equal(f.
mss_fix, 942);
427 assert_int_equal(f.
mss_fix, 926);
441 for (
int i = 900;
i <= 1200;
i++)
449 assert_int_equal(f.
mss_fix,
i - 4 - 4 - 16 - 40);
464 assert_int_equal(aeslimit, (1ull << 36) - 1);
471 assert_int_equal(aeslimit / L, 680390858);
475 assert_int_equal(aeslimit / L, 122059461);
482 uint8_t prk[32] = { 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f,
483 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f,
484 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5 };
486 uint8_t info[10] = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 };
488 uint8_t okm[42] = { 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f,
489 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a,
490 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34,
491 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65 };
496 assert_memory_equal(out, okm,
sizeof(out));
503 uint8_t prk[32] = { 0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c,
504 0x9c, 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46,
505 0x71, 0x01, 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44 };
507 uint8_t info[80] = { 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb,
508 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
509 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3,
510 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
511 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb,
512 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
513 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff };
516 uint8_t okm[82] = { 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c,
517 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
518 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99,
519 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09,
520 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9,
521 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87,
522 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87 };
524 uint8_t out[82] = { 0xaa };
527 assert_memory_equal(out, okm, L);
534 uint8_t prk[32] = { 0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9,
535 0x1d, 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb,
536 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04 };
541 uint8_t okm[42] = { 0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80,
542 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1,
543 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d,
544 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8 };
549 assert_memory_equal(out, okm, L);
558 uint8_t prk[32] = { 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f,
559 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f,
560 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5 };
562 uint8_t info[18] = { 0x00, 0x1b, 0x0e, 0x6f, 0x76, 0x70, 0x6e, 0x20, 0x75,
563 0x6e, 0x69, 0x74, 0x20, 0x74, 0x65, 0x73, 0x74, 0x00 };
566 uint8_t okm[27] = { 0x87, 0x5a, 0x8e, 0xec, 0x18, 0x55, 0x63, 0x80, 0xb8,
567 0xd9, 0x33, 0xed, 0x32, 0x3c, 0x2d, 0xf8, 0xe8, 0xec,
568 0xcf, 0x49, 0x72, 0xe6, 0x83, 0xf0, 0x6a, 0x83, 0xac };
573 assert_memory_equal(out, okm, L);
579 uint8_t secret[32] = { 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f,
580 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f,
581 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5 };
583 const uint8_t *label = (
const uint8_t *)(
"unit test");
587 uint8_t out_expected[16] = { 0x18, 0x5e, 0xaa, 0x1c, 0x7f, 0x22, 0x8a, 0xb8,
588 0xeb, 0x29, 0x77, 0x32, 0x14, 0xd9, 0x20, 0x46 };
590 assert_memory_equal(out, out_expected, 16);
593#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L
600ossl_expand_label(
const uint8_t *secret,
size_t secret_len,
const uint8_t *label,
size_t label_len,
601 const uint8_t *
context,
size_t context_len, uint8_t *out, uint16_t out_len)
604 const char *properties = NULL;
606 const uint8_t *label_prefix = (
const uint8_t *)(
"ovpn ");
607 const size_t label_prefix_len = 5;
609 EVP_KDF *kdf = EVP_KDF_fetch(libctx, OSSL_KDF_NAME_TLS1_3_KDF, properties);
610 assert_non_null(kdf);
612 const char *mdname =
"SHA-256";
616 EVP_KDF_CTX *kctx = EVP_KDF_CTX_new(kdf);
617 assert_non_null(kctx);
619 OSSL_PARAM params[7];
620 OSSL_PARAM *p = params;
622 int mode = EVP_PKEY_HKDEF_MODE_EXPAND_ONLY;
624 *p++ = OSSL_PARAM_construct_int(OSSL_KDF_PARAM_MODE, &mode);
625 *p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, (
char *)mdname, 0);
626 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, (
unsigned char *)secret, hashlen);
627 *p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PREFIX, (
unsigned char *)label_prefix,
630 OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_LABEL, (
unsigned char *)label, label_len);
632 *p++ = OSSL_PARAM_construct_end();
634 int ret = EVP_KDF_derive(kctx, out, out_len, params);
635 EVP_KDF_CTX_free(kctx);
638 assert_int_equal(ret, 1);
645 uint8_t secret[32] = { 0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f,
646 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f,
647 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5 };
649 const uint8_t *label = (
const uint8_t *)(
"unit test");
650 const size_t labellen = 9;
653 ossl_expand_label(secret,
sizeof(secret), label, labellen, NULL, 0, out,
sizeof(out));
656 uint8_t out_ovpn[27];
658 ovpn_expand_label(secret,
sizeof(secret), label, 9, NULL, 0, out_ovpn,
sizeof(out_ovpn));
659 assert_memory_equal(out_ovpn, out,
sizeof(out_ovpn));
680 int *num_future_keys = (
int *)*state;
688 struct epoch_key epoch1send = { .
epoch = 1, .epoch_key = { 0x23 } };
689 struct epoch_key epoch1recv = { .
epoch = 1, .epoch_key = { 0x27 } };
747 for (
int i = 0;
i < 4;
i++)
886 uint8_t exp_cipherkey[24] = { 0xed, 0x85, 0x33, 0xdb, 0x1c, 0x28, 0xac, 0xe4,
887 0x18, 0xe9, 0x00, 0x6a, 0xb2, 0x9c, 0x17, 0x41,
888 0x7d, 0x60, 0xeb, 0xe6, 0xcd, 0x90, 0xbf, 0x0a };
890 uint8_t exp_impl_iv[12] = { 0x86, 0x89, 0x0a, 0xab, 0xf0, 0x32,
891 0xcb, 0x59, 0xf4, 0xcf, 0xa3, 0x4e };
900 int prestate_num13 = 13;
901 int prestate_num16 = 16;
902 int prestate_num32 = 32;
905 const struct CMUnitTest tests[] = {
934#if defined(ENABLE_CRYPTO_OPENSSL)
935 OpenSSL_add_all_algorithms();
938 int ret = cmocka_run_group_tests_name(
"crypto tests", tests, NULL, NULL);
940#if defined(ENABLE_CRYPTO_OPENSSL)
char * string_alloc(const char *str, struct gc_arena *gc)
static void buf_set_write(struct buffer *buf, uint8_t *data, int size)
static void buf_set_read(struct buffer *buf, const uint8_t *data, size_t size)
static void gc_free(struct gc_arena *a)
static struct gc_arena gc_new(void)
#define COMP_ALG_LZO
LZO algorithm.
void free_key_ctx_bi(struct key_ctx_bi *ctx)
void init_key_type(struct key_type *kt, const char *ciphername, const char *authname, bool tls_mode, bool warn)
Initialize a key_type structure with.
uint64_t cipher_get_aead_limits(const char *ciphername)
Check if the cipher is an AEAD cipher and needs to be limited to a certain number of number of blocks...
void free_key_ctx(struct key_ctx *ctx)
Data Channel Cryptography Module.
bool ssl_tls1_PRF(const uint8_t *seed, size_t seed_len, const uint8_t *secret, size_t secret_len, uint8_t *output, size_t output_len)
Calculates the TLS 1.0-1.1 PRF function.
void hmac_ctx_update(hmac_ctx_t *ctx, const uint8_t *src, int src_len)
hmac_ctx_t * hmac_ctx_new(void)
void hmac_ctx_reset(hmac_ctx_t *ctx)
void hmac_ctx_init(hmac_ctx_t *ctx, const uint8_t *key, const char *mdname)
void hmac_ctx_final(hmac_ctx_t *ctx, uint8_t *dst)
bool crypto_pem_decode(const char *name, struct buffer *dst, const struct buffer *src)
Decode a PEM buffer to binary data.
static bool cipher_valid(const char *ciphername)
Returns if the cipher is valid, based on the given cipher name.
void hmac_ctx_free(hmac_ctx_t *ctx)
const char * cipher_kt_name(const char *ciphername)
Retrieve a normalised string describing the cipher (e.g.
void hmac_ctx_cleanup(hmac_ctx_t *ctx)
unsigned char md_kt_size(const char *mdname)
Returns the size of the message digest, in bytes.
bool crypto_pem_encode(const char *name, struct buffer *dst, const struct buffer *src, struct gc_arena *gc)
Encode binary data as PEM.
bool ovpn_expand_label(const uint8_t *secret, size_t secret_len, const uint8_t *label, size_t label_len, const uint8_t *context, size_t context_len, uint8_t *out, uint16_t out_len)
Variant of the RFC 8446 TLS 1.3 HKDF-Expand-Label function with the following differences/restriction...
void epoch_generate_future_receive_keys(struct crypto_options *co)
Generates and fills the epoch_data_keys_future with next valid future keys in crypto_options using th...
void epoch_replace_update_recv_key(struct crypto_options *co, uint16_t new_epoch)
This is called when the peer uses a new send key that is not the default key.
void free_epoch_key_ctx(struct crypto_options *co)
Frees the extra data structures used by epoch keys in crypto_options.
struct key_ctx * epoch_lookup_decrypt_key(struct crypto_options *opt, uint16_t epoch)
Using an epoch, this function will try to retrieve a decryption key context that matches that epoch f...
void epoch_init_key_ctx(struct crypto_options *co, const struct key_type *key_type, const struct epoch_key *e1_send, const struct epoch_key *e1_recv, uint16_t future_key_count)
Initialises data channel keys and internal structures for epoch data keys using the provided E0 epoch...
void epoch_data_key_derive(struct key_parameters *key, const struct epoch_key *epoch_key, const struct key_type *kt)
Generate a data channel key pair from the epoch key.
void ovpn_hkdf_expand(const uint8_t *secret, const uint8_t *info, int info_len, uint8_t *out, int out_len)
Implementation of the RFC5869 HKDF-Expand function with the following restrictions.
void epoch_iterate_send_key(struct crypto_options *co)
Updates the send key and send_epoch_key in cryptio_options->key_ctx_bi to use the next epoch.
mbedtls_md_context_t hmac_ctx_t
Generic HMAC context.
#define SHA256_DIGEST_LENGTH
void frame_calculate_dynamic(struct frame *frame, struct key_type *kt, const struct options *options, struct link_socket_info *lsi)
Set the –mssfix option.
size_t calc_options_string_link_mtu(const struct options *o, const struct frame *frame)
Calculate the link-mtu to advertise to our peer.
Control Channel SSL library backend module.
Wrapper structure for dynamically allocated memory.
int len
Length in bytes of the actual content within the allocated memory.
const char * socks_proxy_server
Contains all state information for one tunnel.
Security parameter state for processing data channel packets.
struct epoch_key epoch_key_send
last epoch_key used for generation of the current send data keys.
struct key_ctx epoch_retiring_data_receive_key
The old key before the sender switched to a new epoch data key.
struct key_ctx * epoch_data_keys_future
Keeps the future epoch data keys for decryption.
struct key_ctx_bi key_ctx_bi
OpenSSL cipher and HMAC contexts for both sending and receiving directions.
uint16_t epoch_data_keys_future_count
number of keys stored in epoch_data_keys_future
struct epoch_key epoch_key_recv
epoch_key used for the highest receive epoch keys
Packet geometry parameters.
uint16_t mss_fix
The actual MSS value that should be written to the payload packets.
Garbage collection arena used to keep track of dynamically allocated memory.
struct key_ctx decrypt
cipher and/or HMAC contexts for receiving direction.
struct key_ctx encrypt
Cipher and/or HMAC contexts for sending direction.
uint16_t epoch
OpenVPN data channel epoch, this variable holds the epoch number this key belongs to.
internal structure similar to struct key that holds key information but is not represented on wire an...
int hmac_size
Number of bytes set in the HMac key material.
int cipher_size
Number of bytes set in the cipher key material.
uint8_t hmac[MAX_HMAC_KEY_LENGTH]
Key material for HMAC operations.
uint8_t cipher[MAX_CIPHER_KEY_LENGTH]
Key material for cipher operations.
Container for unidirectional cipher and HMAC key material.
struct compress_options comp
const char * tls_auth_file
struct connection_entry ce
const char * shared_secret_file
static void openvpn_unit_test_setup(void)
Sets up the environment for unit tests like making both stderr and stdout non-buffered to avoid messa...
void crypto_test_ovpn_label_expand(void **state)
void crypto_test_hkdf_expand_testa2(void **state)
static void test_mssfix_mtu_calculation(void **state)
void crypto_test_hkdf_expand_testa1(void **state)
static uint8_t testkey[20]
static void test_cipher_names(const char *ciphername, const char *openvpn_name)
void crypto_test_hkdf_expand_testa3(void **state)
void crypto_test_ovpn_expand_openssl3(void **state)
static void test_translate_cipher(const char *ciphername, const char *openvpn_name)
static void crypto_translate_cipher_names(void **state)
void crypto_test_epoch_key_receive_lookup(void **state)
void crypto_test_epoch_key_rotation(void **state)
static uint8_t goodhash[20]
static const char testtext[]
static int crypto_test_epoch_teardown(void **state)
static void crypto_test_hmac(void **state)
void crypto_test_aead_limits(void **state)
static void crypto_pem_encode_decode_loopback(void **state)
void crypto_test_epoch_key_generation(void **state)
static const char * ipsumlorem
static int crypto_test_epoch_setup(void **state)
void epoch_test_derive_data_key(void **state)
void crypto_test_epoch_key_overflow(void **state)
static void crypto_test_tls_prf(void **state)
static void test_occ_mtu_calculation(void **state)
void crypto_test_hkdf_expand_test_ovpn(void **state)