OpenVPN
test_ssl.c
Go to the documentation of this file.
1 /*
2  * OpenVPN -- An application to securely tunnel IP networks
3  * over a single UDP port, with support for SSL/TLS-based
4  * session authentication and key exchange,
5  * packet encryption, packet authentication, and
6  * packet compression.
7  *
8  * Copyright (C) 2023-2024 OpenVPN Inc <sales@openvpn.net>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include "syshead.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <setjmp.h>
35 #include <cmocka.h>
36 
37 #include "crypto.h"
38 #include "options.h"
39 #include "ssl_backend.h"
40 #include "options_util.h"
41 
42 #include "mock_msg.h"
43 #include "mss.h"
44 #include "ssl_verify_backend.h"
45 #include "win32.h"
46 #include "test_common.h"
47 #include "ssl.h"
48 #include "buffer.h"
49 #include "packet_id.h"
50 
51 /* Mock function to be allowed to include win32.c which is required for
52  * getting the temp directory */
53 #ifdef _WIN32
54 struct signal_info siginfo_static; /* GLOBAL */
55 
56 const char *
57 strerror_win32(DWORD errnum, struct gc_arena *gc)
58 {
59  ASSERT(false);
60 }
61 
62 void
63 throw_signal(const int signum)
64 {
65  ASSERT(false);
66 }
67 #endif
68 
69 
70 const char *unittest_cert = "-----BEGIN CERTIFICATE-----\n"
71  "MIIBuTCCAUCgAwIBAgIUTLtjSBzx53qZRvZ6Ur7D9kgoOHkwCgYIKoZIzj0EAwIw\n"
72  "EzERMA8GA1UEAwwIdW5pdHRlc3QwIBcNMjMxMTIxMDk1NDQ3WhgPMjA3ODA4MjQw\n"
73  "OTU0NDdaMBMxETAPBgNVBAMMCHVuaXR0ZXN0MHYwEAYHKoZIzj0CAQYFK4EEACID\n"
74  "YgAEHYB2hn2xx3f4lClXDtdi36P19pMZA+kI1Dkv/Vn10vBZ/j9oa+P99T8duz/e\n"
75  "QlPeHpesNJO4fX8iEDj6+vMeWejOT7jAQ4MmG5EZjpcBKxCfwFooEvzu8bVujUcu\n"
76  "wTQEo1MwUTAdBgNVHQ4EFgQUPcgBEVXjF5vYfDsInoE3dF6UfQswHwYDVR0jBBgw\n"
77  "FoAUPcgBEVXjF5vYfDsInoE3dF6UfQswDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjO\n"
78  "PQQDAgNnADBkAjBLPAGrQAyinigqiu0RomoV8TVaknVLFSq6H6A8jgvzfsFCUK1O\n"
79  "dvNZhFPM6idKB+oCME2JLOBANCSV8o7aJzq7SYHKwPyb1J4JFlwKe/0Jpv7oh9b1\n"
80  "IJbuaM9Z/VSKbrIXGg==\n"
81  "-----END CERTIFICATE-----\n";
82 
83 static const char *
85 {
86  const char *ret;
87 #ifdef _WIN32
88  ret = win_get_tempdir();
89 #else
90  ret = "/tmp";
91 #endif
92  assert_non_null(ret);
93  return ret;
94 }
95 
96 static void
98 {
99  struct gc_arena gc = gc_new();
100 
101  struct tls_root_ctx ctx = { 0 };
104 
105  openvpn_x509_cert_t *cert = NULL;
106 
107  /* we do not have methods to fetch certificates from ssl contexts, use
108  * internal TLS library methods for the unit test */
109 #ifdef ENABLE_CRYPTO_OPENSSL
110  cert = SSL_CTX_get0_certificate(ctx.ctx);
111 #elif defined(ENABLE_CRYPTO_MBEDTLS)
112  cert = ctx.crt_chain;
113 #endif
114 
115  const char *tmpfile = platform_create_temp_file(get_tmp_dir(), "ut_pem", &gc);
116  backend_x509_write_pem(cert, tmpfile);
117 
118  struct buffer exported_pem = buffer_read_from_file(tmpfile, &gc);
119  assert_string_equal(BSTR(&exported_pem), unittest_cert);
120 
121  tls_ctx_free(&ctx);
122  unlink(tmpfile);
123  gc_free(&gc);
124 }
125 
126 static void
128 {
129  cipher_ctx_t *cipher = co->key_ctx_bi.encrypt.cipher;
130 
131  if (cipher_ctx_mode_aead(cipher))
132  {
133  size_t impl_iv_len = cipher_ctx_iv_length(cipher) - sizeof(packet_id_type);
136 
137  /* Generate dummy implicit IV */
140  co->key_ctx_bi.encrypt.implicit_iv_len = impl_iv_len;
141 
142  memcpy(co->key_ctx_bi.decrypt.implicit_iv,
144  co->key_ctx_bi.decrypt.implicit_iv_len = impl_iv_len;
145  }
146 }
147 
148 static void
150 {
151  int overhead = 0;
152 
153  /* tls-auth and tls-crypt */
154  overhead += 128;
155 
156  /* TCP length field and opcode */
157  overhead += 3;
158 
159  /* ACK array and remote SESSION ID (part of the ACK array) */
160  overhead += ACK_SIZE(RELIABLE_ACK_SIZE);
161 
162  /* Previous OpenVPN version calculated the maximum size and buffer of a
163  * control frame depending on the overhead of the data channel frame
164  * overhead and limited its maximum size to 1250. Since control frames
165  * also need to fit into data channel buffer we have the same
166  * default of 1500 + 100 as data channel buffers have. Increasing
167  * control channel mtu beyond this limit also increases the data channel
168  * buffers */
169  int tls_mtu = 1500;
170  frame->buf.payload_size = tls_mtu + 100;
171 
172  frame->buf.headroom = overhead;
173  frame->buf.tailroom = overhead;
174 
175  frame->tun_mtu = tls_mtu;
176 
177 }
178 
179 static void
181 {
182  struct gc_arena gc = gc_new();
183 
184  /* initialise frame for the test */
185  struct frame frame;
187 
188  struct buffer src = alloc_buf_gc(frame.buf.payload_size, &gc);
189  struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
190  struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
191  struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
192  struct buffer buf = clear_buf();
193  void *buf_p;
194 
195  /* init work */
196  ASSERT(buf_init(&work, frame.buf.headroom));
197 
198  init_implicit_iv(co);
199  update_time();
200 
201  /* Test encryption, decryption for all packet sizes */
202  for (int i = 1; i <= frame.buf.payload_size; ++i)
203  {
204 
205  /* msg(M_INFO, "TESTING ENCRYPT/DECRYPT of packet length=%d", i); */
206 
207  /*
208  * Load src with random data.
209  */
210  ASSERT(buf_init(&src, 0));
211  ASSERT(i <= src.capacity);
212  src.len = i;
213  ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
214 
215  /* copy source to input buf */
216  buf = work;
217  buf_p = buf_write_alloc(&buf, BLEN(&src));
218  ASSERT(buf_p);
219  memcpy(buf_p, BPTR(&src), BLEN(&src));
220 
221  /* initialize work buffer with buf.headroom bytes of prepend capacity */
222  ASSERT(buf_init(&encrypt_workspace, frame.buf.headroom));
223 
224  /* encrypt */
225  openvpn_encrypt(&buf, encrypt_workspace, co);
226 
227  /* decrypt */
228  openvpn_decrypt(&buf, decrypt_workspace, co, &frame, BPTR(&buf));
229 
230  /* compare */
231  assert_int_equal(buf.len, src.len);
232  assert_memory_equal(BPTR(&src), BPTR(&buf), i);
233 
234  }
235  gc_free(&gc);
236 }
237 
238 
239 
240 struct crypto_options
241 init_crypto_options(const char *cipher, const char *auth)
242 {
243  struct key2 key2 = { .n = 2};
244 
245  ASSERT(rand_bytes(key2.keys[0].cipher, sizeof(key2.keys[0].cipher)));
246  ASSERT(rand_bytes(key2.keys[0].hmac, sizeof(key2.keys[0].hmac)));
247  ASSERT(rand_bytes(key2.keys[1].cipher, sizeof(key2.keys[1].cipher)));
248  ASSERT(rand_bytes(key2.keys[1].hmac, sizeof(key2.keys)[1].hmac));
249 
250  struct crypto_options co = { 0 };
251 
252  struct key_type kt = create_kt(cipher, auth, "ssl-test");
253 
254  init_key_ctx_bi(&co.key_ctx_bi, &key2, 0, &kt, "unit-test-ssl");
255  packet_id_init(&co.packet_id, 5, 5, "UNITTEST", 0);
256 
257  return co;
258 }
259 
260 static void
262 {
265 
266 }
267 
268 
269 static void
270 run_data_channel_with_cipher(const char *cipher, const char *auth)
271 {
272  struct crypto_options co = init_crypto_options(cipher, auth);
275 }
276 
277 static void
279 {
280  run_data_channel_with_cipher("AES-128-GCM", "none");
281 }
282 
283 static void
285 {
286  run_data_channel_with_cipher("AES-192-GCM", "none");
287 }
288 
289 static void
291 {
292  run_data_channel_with_cipher("AES-256-GCM", "none");
293 }
294 
295 static void
297 {
298  run_data_channel_with_cipher("AES-128-CBC", "SHA256");
299 }
300 
301 static void
303 {
304  run_data_channel_with_cipher("AES-192-CBC", "SHA256");
305 }
306 
307 static void
309 {
310  run_data_channel_with_cipher("AES-256-CBC", "SHA256");
311 }
312 
313 static void
315 {
316  if (!cipher_valid("ChaCha20-Poly1305"))
317  {
318  skip();
319  return;
320  }
321  run_data_channel_with_cipher("ChaCha20-Poly1305", "none");
322 }
323 
324 static void
326 {
327  if (!cipher_valid("BF-CBC"))
328  {
329  skip();
330  return;
331  }
332  run_data_channel_with_cipher("BF-CBC", "SHA1");
333 }
334 
335 
336 int
337 main(void)
338 {
340 
341  const struct CMUnitTest tests[] = {
342  cmocka_unit_test(crypto_pem_encode_certificate),
343  cmocka_unit_test(test_data_channel_roundtrip_aes_128_gcm),
344  cmocka_unit_test(test_data_channel_roundtrip_aes_192_gcm),
345  cmocka_unit_test(test_data_channel_roundtrip_aes_256_gcm),
347  cmocka_unit_test(test_data_channel_roundtrip_aes_128_cbc),
348  cmocka_unit_test(test_data_channel_roundtrip_aes_192_cbc),
349  cmocka_unit_test(test_data_channel_roundtrip_aes_256_cbc),
350  cmocka_unit_test(test_data_channel_roundtrip_bf_cbc),
351  };
352 
353 #if defined(ENABLE_CRYPTO_OPENSSL)
354  tls_init_lib();
355 #endif
356 
357  int ret = cmocka_run_group_tests_name("ssl tests", tests, NULL, NULL);
358 
359 #if defined(ENABLE_CRYPTO_OPENSSL)
360  tls_free_lib();
361 #endif
362 
363  return ret;
364 }
buffer_read_from_file
struct buffer buffer_read_from_file(const char *filename, struct gc_arena *gc)
buffer_read_from_file - copy the content of a file into a buffer
Definition: buffer.c:1376
platform_create_temp_file
const char * platform_create_temp_file(const char *directory, const char *prefix, struct gc_arena *gc)
Create a temporary file in directory, returns the filename of the created file.
Definition: platform.c:554
tls_ctx_load_cert_file
void tls_ctx_load_cert_file(struct tls_root_ctx *ctx, const char *cert_file, bool cert_file_inline)
Load certificate file into the given TLS context.
Definition: ssl_openssl.c:949
cipher_valid
static bool cipher_valid(const char *ciphername)
Returns if the cipher is valid, based on the given cipher name.
Definition: crypto_backend.h:204
key2::n
int n
The number of key objects stored in the key2.keys array.
Definition: crypto.h:181
cipher_ctx_iv_length
int cipher_ctx_iv_length(const cipher_ctx_t *ctx)
Returns the size of the IV used by the cipher, in bytes, or 0 if no IV is used.
ssl_backend.h
gc_new
static struct gc_arena gc_new(void)
Definition: buffer.h:1030
ssl_verify_backend.h
tls_init_lib
void tls_init_lib(void)
Perform any static initialisation necessary by the library.
Definition: ssl_openssl.c:85
OPENVPN_AEAD_MIN_IV_LEN
#define OPENVPN_AEAD_MIN_IV_LEN
Minimal IV length for AEAD mode ciphers (in bytes): 4-byte packet id + 8 bytes implicit IV.
Definition: crypto.h:294
RELIABLE_ACK_SIZE
#define RELIABLE_ACK_SIZE
The maximum number of packet IDs waiting to be acknowledged which can be stored in one reliable_ack s...
Definition: reliable.h:44
buffer::len
int len
Length in bytes of the actual content within the allocated memory.
Definition: buffer.h:66
packet_id_init
void packet_id_init(struct packet_id *p, int seq_backtrack, int time_backtrack, const char *name, int unit)
Definition: packet_id.c:79
win32.h
test_data_channel_roundtrip_bf_cbc
static void test_data_channel_roundtrip_bf_cbc(void **state)
Definition: test_ssl.c:325
buf_init
#define buf_init(buf, offset)
Definition: buffer.h:209
test_common.h
BSTR
#define BSTR(buf)
Definition: buffer.h:129
test_data_channel_roundtrip_aes_128_gcm
static void test_data_channel_roundtrip_aes_128_gcm(void **state)
Definition: test_ssl.c:278
tls_ctx_client_new
void tls_ctx_client_new(struct tls_root_ctx *ctx)
Initialises a library-specific TLS context for a client.
Definition: ssl_openssl.c:115
buffer::capacity
int capacity
Size in bytes of memory allocated by malloc().
Definition: buffer.h:62
alloc_buf_gc
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:88
throw_signal
void throw_signal(const int signum)
Throw a hard signal.
Definition: test_ssl.c:63
key_ctx::cipher
cipher_ctx_t * cipher
Generic cipher context.
Definition: crypto.h:164
frame::tailroom
int tailroom
the tailroom in the buffer.
Definition: mtu.h:112
key_ctx_bi::encrypt
struct key_ctx encrypt
Cipher and/or HMAC contexts for sending direction.
Definition: crypto.h:219
tls_free_lib
void tls_free_lib(void)
Free any global SSL library-specific data structures.
Definition: ssl_openssl.c:92
clear_buf
static struct buffer clear_buf(void)
Return an empty struct buffer.
Definition: buffer.h:222
options.h
key::hmac
uint8_t hmac[MAX_HMAC_KEY_LENGTH]
Key material for HMAC operations.
Definition: crypto.h:153
init_crypto_options
struct crypto_options init_crypto_options(const char *cipher, const char *auth)
Definition: test_ssl.c:241
frame
Packet geometry parameters.
Definition: mtu.h:98
backend_x509_write_pem
result_t backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
Definition: ssl_verify_openssl.c:324
crypto_pem_encode_certificate
static void crypto_pem_encode_certificate(void **state)
Definition: test_ssl.c:97
get_tmp_dir
static const char * get_tmp_dir(void)
Definition: test_ssl.c:84
init_key_ctx_bi
void init_key_ctx_bi(struct key_ctx_bi *ctx, const struct key2 *key2, int key_direction, const struct key_type *kt, const char *name)
Definition: crypto.c:869
test_data_channel_roundtrip_aes_192_gcm
static void test_data_channel_roundtrip_aes_192_gcm(void **state)
Definition: test_ssl.c:284
options_util.h
free_key_ctx_bi
void free_key_ctx_bi(struct key_ctx_bi *ctx)
Definition: crypto.c:906
ASSERT
#define ASSERT(x)
Definition: error.h:195
unittest_cert
const char * unittest_cert
Definition: test_ssl.c:70
packet_id.h
BLEN
#define BLEN(buf)
Definition: buffer.h:127
frame::payload_size
int payload_size
the maximum size that a payload that our buffers can hold from either tun device or network link.
Definition: mtu.h:102
update_time
static void update_time(void)
Definition: otime.h:77
test_data_channel_roundtrip_aes_256_cbc
static void test_data_channel_roundtrip_aes_256_cbc(void **state)
Definition: test_ssl.c:308
cipher_ctx_t
mbedtls_cipher_context_t cipher_ctx_t
Generic cipher context.
Definition: crypto_mbedtls.h:40
openvpn_encrypt
void openvpn_encrypt(struct buffer *buf, struct buffer work, struct crypto_options *opt)
Encrypt and HMAC sign a packet so that it can be sent as a data channel VPN tunnel packet to a remote...
Definition: crypto.c:295
test_data_channel_roundtrip_chacha20_poly1305
static void test_data_channel_roundtrip_chacha20_poly1305(void **state)
Definition: test_ssl.c:314
siginfo_static
struct signal_info siginfo_static
Definition: test_ssl.c:54
crypto.h
tls_ctx_free
void tls_ctx_free(struct tls_root_ctx *ctx)
Frees the library-specific TLSv1 context.
Definition: ssl_openssl.c:133
openvpn_decrypt
bool openvpn_decrypt(struct buffer *buf, struct buffer work, struct crypto_options *opt, const struct frame *frame, const uint8_t *ad_start)
HMAC verify and decrypt a data channel packet received from a remote OpenVPN peer.
Definition: crypto.c:645
cipher_ctx_mode_aead
bool cipher_ctx_mode_aead(const cipher_ctx_t *ctx)
Check if the supplied cipher is a supported AEAD mode cipher.
Definition: crypto_openssl.c:939
packet_id_type
uint32_t packet_id_type
Definition: packet_id.h:44
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
OPENVPN_MAX_IV_LENGTH
#define OPENVPN_MAX_IV_LENGTH
Maximum length of an IV.
Definition: crypto_mbedtls.h:52
test_data_channel_roundtrip_aes_256_gcm
static void test_data_channel_roundtrip_aes_256_gcm(void **state)
Definition: test_ssl.c:290
key_ctx::implicit_iv_len
size_t implicit_iv_len
The length of implicit_iv.
Definition: crypto.h:168
rand_bytes
int rand_bytes(uint8_t *output, int len)
Wrapper for secure random number generator.
Definition: crypto_openssl.c:592
key_type
Definition: crypto.h:139
mock_msg.h
init_implicit_iv
static void init_implicit_iv(struct crypto_options *co)
Definition: test_ssl.c:127
strerror_win32
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
Definition: test_ssl.c:57
ssl.h
buffer.h
key_ctx::implicit_iv
uint8_t implicit_iv[OPENVPN_MAX_IV_LENGTH]
The implicit part of the IV.
Definition: crypto.h:166
frame::buf
struct frame::@6 buf
syshead.h
BPTR
#define BPTR(buf)
Definition: buffer.h:124
create_kt
static struct key_type create_kt(const char *cipher, const char *md, const char *optname)
Creates and validates an instance of struct key_type with the provided algs.
Definition: crypto.h:576
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
key_type::cipher
const char * cipher
const name of the cipher
Definition: crypto.h:141
init_frame_parameters
static void init_frame_parameters(struct frame *frame)
Definition: test_ssl.c:149
do_data_channel_round_trip
static void do_data_channel_round_trip(struct crypto_options *co)
Definition: test_ssl.c:180
openvpn_unit_test_setup
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...
Definition: test_common.h:36
openvpn_x509_cert_t
X509 openvpn_x509_cert_t
Definition: openvpn-plugin.h:40
main
int main(void)
Definition: test_ssl.c:337
tls_root_ctx
Structure that wraps the TLS context.
Definition: ssl_mbedtls.h:106
signal_info
Definition: sig.h:41
gc_free
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1038
BUF_SIZE
#define BUF_SIZE(f)
Definition: mtu.h:172
win_get_tempdir
const char * win_get_tempdir(void)
Definition: win32-util.c:152
mss.h
key::cipher
uint8_t cipher[MAX_CIPHER_KEY_LENGTH]
Key material for cipher operations.
Definition: crypto.h:151
crypto_options::key_ctx_bi
struct key_ctx_bi key_ctx_bi
OpenSSL cipher and HMAC contexts for both sending and receiving directions.
Definition: crypto.h:232
buf_write_alloc
static uint8_t * buf_write_alloc(struct buffer *buf, size_t size)
Definition: buffer.h:640
config.h
run_data_channel_with_cipher
static void run_data_channel_with_cipher(const char *cipher, const char *auth)
Definition: test_ssl.c:270
test_data_channel_roundtrip_aes_128_cbc
static void test_data_channel_roundtrip_aes_128_cbc(void **state)
Definition: test_ssl.c:296
test_data_channel_roundtrip_aes_192_cbc
static void test_data_channel_roundtrip_aes_192_cbc(void **state)
Definition: test_ssl.c:302
tls_root_ctx::ctx
SSL_CTX * ctx
Definition: ssl_openssl.h:40
key2
Container for bidirectional cipher and HMAC key material.
Definition: crypto.h:179
crypto_options::packet_id
struct packet_id packet_id
Current packet ID state for both sending and receiving directions.
Definition: crypto.h:236
key2::keys
struct key keys[2]
Two unidirectional sets of key material.
Definition: crypto.h:183
packet_id_free
void packet_id_free(struct packet_id *p)
Definition: packet_id.c:102
uninit_crypto_options
static void uninit_crypto_options(struct crypto_options *co)
Definition: test_ssl.c:261
ACK_SIZE
#define ACK_SIZE(n)
Definition: reliable.h:68
frame::tun_mtu
int tun_mtu
the (user) configured tun-mtu.
Definition: mtu.h:131
key_ctx_bi::decrypt
struct key_ctx decrypt
cipher and/or HMAC contexts for receiving direction.
Definition: crypto.h:221
frame::headroom
int headroom
the headroom in the buffer, this is choosen to allow all potential header to be added before the pack...
Definition: mtu.h:108
crypto_options
Security parameter state for processing data channel packets.
Definition: crypto.h:230