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-2026 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, see <https://www.gnu.org/licenses/>.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "syshead.h"
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <stdarg.h>
32#include <string.h>
33#include <setjmp.h>
34#include <cmocka.h>
35
36#include "crypto.h"
37#include "crypto_epoch.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 "cert_data.h"
50#include "packet_id.h"
51#include "ssl_util.h"
52#include "ssl_verify.h"
53#include "openvpn.h"
54
55/* Mock function to be allowed to include win32.c which is required for
56 * getting the temp directory */
57#ifdef _WIN32
58struct signal_info siginfo_static; /* GLOBAL */
59
60const char *
61strerror_win32(DWORD errnum, struct gc_arena *gc)
62{
63 ASSERT(false);
64}
65
66void
67throw_signal(const int signum)
68{
69 ASSERT(false);
70}
71#endif
72
73#if defined(ENABLE_CRYPTO_OPENSSL) && (OPENSSL_VERSION_NUMBER > 0x30000000L)
74#define HAVE_OPENSSL_STORE
75#endif
76
77/* stubs for some unused functions instead of pulling in too many dependencies */
78bool
79get_user_pass_cr(struct user_pass *up, const char *auth_file, const char *prefix,
80 const unsigned int flags, const char *auth_challenge)
81{
82 return false;
83}
84void
85purge_user_pass(struct user_pass *up, bool force)
86{
87 return;
88}
89
90/* generated using
91 * openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -keyout - \
92 * -noenc -sha256 -days 3650 -subj '/CN=ovpn-test-secp384r1' -nodes \
93 * -addext 'subjectAltName=DNS:unittest.example.com' \
94 * -addext 'extendedKeyUsage=clientAuth'
95 */
96static const char *const unittest_cert =
97 "-----BEGIN CERTIFICATE-----\n"
98 "MIICBjCCAYygAwIBAgIUFoXgpP4beykV7tpgrjHQTWPGi4cwCgYIKoZIzj0EAwIw\n"
99 "HjEcMBoGA1UEAwwTb3Zwbi10ZXN0LXNlY3AzODRyMTAeFw0yNTA5MDgxMzExNTBa\n"
100 "Fw0zNTA5MDYxMzExNTBaMB4xHDAaBgNVBAMME292cG4tdGVzdC1zZWNwMzg0cjEw\n"
101 "djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQVDmf+TZB3rW6zqWFox606u/PhA93ysX/h\n"
102 "1s2xyq9+QGzIdE/hks6p/Yzyu7RLOUjxvO0J45RHcYmo67DlvSOi496T3zrgvp1H\n"
103 "KfHD5ohMyvzw0+e8lmjJqJjn+PegMkOjgYowgYcwHQYDVR0OBBYEFCH1eYnaV8fh\n"
104 "E3Bv7lyrlYu24eoVMB8GA1UdIwQYMBaAFCH1eYnaV8fhE3Bv7lyrlYu24eoVMA8G\n"
105 "A1UdEwEB/wQFMAMBAf8wHwYDVR0RBBgwFoIUdW5pdHRlc3QuZXhhbXBsZS5jb20w\n"
106 "EwYDVR0lBAwwCgYIKwYBBQUHAwIwCgYIKoZIzj0EAwIDaAAwZQIxAL7q7jcwTOuq\n"
107 "5sp0Beq81Vnznd3gsDZYNs1OYRWH33xergDVKlBb6kCwus0dhghtVAIwIgT4ytkY\n"
108 "oAPx8LB3oP8ubEu1ue6V9jZln/cCiLyXDDtaiJOZHtDqHGfHqvc6rAok\n"
109 "-----END CERTIFICATE-----\n";
110
111static const char *const unittest_key =
112 "-----BEGIN PRIVATE KEY-----\n"
113 "MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAXBC7tpa9UepoMVZlM\n"
114 "OxUubkECGK7aWFebxDc3UPoEQemEPMOCdkWBSU/t7Mm4R66hZANiAAQVDmf+TZB3\n"
115 "rW6zqWFox606u/PhA93ysX/h1s2xyq9+QGzIdE/hks6p/Yzyu7RLOUjxvO0J45RH\n"
116 "cYmo67DlvSOi496T3zrgvp1HKfHD5ohMyvzw0+e8lmjJqJjn+PegMkM=\n"
117 "-----END PRIVATE KEY-----\n";
118
119
120static struct
121{
122 struct gc_arena gc;
123 const char *certfile;
124 const char *keyfile;
126
127static int
128init(void **state)
129{
130 (void)state;
131 global_state.gc = gc_new();
134
135 int certfd = open(global_state.certfile, O_RDWR);
136 int keyfd = open(global_state.keyfile, O_RDWR);
137 if (certfd < 0 || keyfd < 0)
138 {
139 fail_msg("make tmpfile for certificate or key data failed (error = %d)", errno);
140 }
141 /* Awkward casts required for MinGW with -O0 only */
142 assert_int_equal(write(certfd, unittest_cert, (unsigned int)strlen(unittest_cert)),
143 strlen(unittest_cert));
144 assert_int_equal(write(keyfd, unittest_key, (unsigned int)strlen(unittest_key)),
145 strlen(unittest_key));
146 close(certfd);
147 close(keyfd);
148 return 0;
149}
150
151static int
152cleanup(void **state)
153{
154 (void)state;
155 unlink(global_state.certfile);
156 unlink(global_state.keyfile);
158 return 0;
159}
160
161static void
163{
164 struct gc_arena gc = gc_new();
165
166 struct tls_root_ctx ctx = { 0 };
169
170 openvpn_x509_cert_t *cert = NULL;
171
172 /* we do not have methods to fetch certificates from ssl contexts, use
173 * internal TLS library methods for the unit test */
174#ifdef ENABLE_CRYPTO_OPENSSL
175 cert = SSL_CTX_get0_certificate(ctx.ctx);
176#elif defined(ENABLE_CRYPTO_MBEDTLS)
177 cert = ctx.crt_chain;
178#endif
179
180 const char *tmpfile = platform_create_temp_file(platform_get_tmp_dir(), "ut_pem", &gc);
181 backend_x509_write_pem(cert, tmpfile);
182
185
186 tls_ctx_free(&ctx);
188 gc_free(&gc);
189}
190
191static void
193{
194 (void)state;
195 struct tls_root_ctx ctx = { 0 };
196
197 /* test loading of inlined cert and key.
198 * loading the key also checks that it matches the loaded certificate
199 */
202 assert_int_equal(tls_ctx_load_priv_file(&ctx, unittest_key, true), 0);
204
205 /* test loading of cert and key from file */
207 tls_ctx_load_cert_file(&ctx, global_state.certfile, false);
208 assert_int_equal(tls_ctx_load_priv_file(&ctx, global_state.keyfile, false), 0);
210}
211
212/* test loading cert and key using file:/path URI */
213static void
215{
216 (void)state;
217
218#if !defined(HAVE_OPENSSL_STORE)
219 skip();
220#else /* HAVE_OPENSSL_STORE */
221
222 struct tls_root_ctx ctx = { 0 };
223 const char *certfile = global_state.certfile;
224 const char *keyfile = global_state.keyfile;
225 struct gc_arena *gc = &global_state.gc;
226
227 struct buffer certuri = alloc_buf_gc(6 + strlen(certfile) + 1, gc); /* 6 bytes for "file:/" */
228 struct buffer keyuri = alloc_buf_gc(6 + strlen(keyfile) + 1, gc); /* 6 bytes for "file:/" */
229
230 /* Windows temp file path starts with drive letter -- add a leading slash for URI */
231 const char *lead = "";
232#ifdef _WIN32
233 lead = "/";
234#endif /* _WIN32 */
235 assert_true(buf_printf(&certuri, "file:%s%s", lead, certfile));
236 assert_true(buf_printf(&keyuri, "file:%s%s", lead, keyfile));
237
238 /* On Windows replace any '\' in path by '/' required for URI */
239#ifdef _WIN32
242#endif /* _WIN32 */
243
244 tls_ctx_new(&ctx);
245 tls_ctx_load_cert_file(&ctx, BSTR(&certuri), false);
247 tls_ctx_free(&ctx);
248#endif /* HAVE_OPENSSL_STORE */
249}
250
251
252static void
254{
255 int overhead = 0;
256
257 /* tls-auth and tls-crypt */
258 overhead += 128;
259
260 /* TCP length field and opcode */
261 overhead += 3;
262
263 /* ACK array and remote SESSION ID (part of the ACK array) */
265
266 /* Previous OpenVPN version calculated the maximum size and buffer of a
267 * control frame depending on the overhead of the data channel frame
268 * overhead and limited its maximum size to 1250. Since control frames
269 * also need to fit into data channel buffer we have the same
270 * default of 1500 + 100 as data channel buffers have. Increasing
271 * control channel mtu beyond this limit also increases the data channel
272 * buffers */
273 int tls_mtu = 1500;
274 frame->buf.payload_size = tls_mtu + 100;
275
278
279 frame->tun_mtu = tls_mtu;
280}
281
282static void
284{
285 struct gc_arena gc = gc_new();
286
287 /* initialise frame for the test */
288 struct frame frame;
290
292 struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
295 struct buffer buf = clear_buf();
296 void *buf_p;
297
298 /* init work */
300
301 update_time();
302
303 /* Test encryption, decryption for all packet sizes */
304 for (int i = 1; i <= frame.buf.payload_size; ++i)
305 {
306 /* msg(M_INFO, "TESTING ENCRYPT/DECRYPT of packet length=%d", i); */
307
308 /*
309 * Load src with random data.
310 */
311 ASSERT(buf_init(&src, 0));
312 ASSERT(i <= src.capacity);
313 src.len = i;
314 prng_bytes(BPTR(&src), BLEN(&src));
315
316 /* copy source to input buf */
317 buf = work;
318 buf_p = buf_write_alloc(&buf, BLENZ(&src));
319 ASSERT(buf_p);
320 memcpy(buf_p, BPTR(&src), BLENZ(&src));
321
322 /* initialize work buffer with buf.headroom bytes of prepend capacity */
324
325 /* encrypt */
327
328 /* decrypt */
329 openvpn_decrypt(&buf, decrypt_workspace, co, &frame, BPTR(&buf));
330
331 /* compare */
332 assert_int_equal(buf.len, src.len);
333 assert_memory_equal(BPTR(&src), BPTR(&buf), i);
334 }
335 gc_free(&gc);
336}
337
338static void
340{
341 struct frame frame;
343
344 struct gc_arena gc = gc_new();
347 struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
348 struct buffer buf = clear_buf();
350 void *buf_p;
351
353
354 /*
355 * Load src with random data.
356 */
357 ASSERT(buf_init(&src, 0));
358 ASSERT(len <= src.capacity);
359 src.len = len;
360 prng_bytes(BPTR(&src), BLEN(&src));
361
362 /* copy source to input buf */
363 buf = work;
364 buf_p = buf_write_alloc(&buf, BLENZ(&src));
365 ASSERT(buf_p);
366 memcpy(buf_p, BPTR(&src), BLENZ(&src));
367
370
371 /* decrypt */
372 openvpn_decrypt(&buf, decrypt_workspace, co, &frame, BPTR(&buf));
373
374 /* compare */
375 assert_int_equal(buf.len, src.len);
377
378 gc_free(&gc);
379}
380
381
382static void
384{
385 /* Check that we correctly react when we have a nearing AEAD limits */
386
387 /* manually increase the send counter to be past
388 * the GCM usage limit */
389 co->key_ctx_bi.encrypt.plaintext_blocks = 0x1ull << 40;
390
391
392 bool epoch = (co->flags & CO_EPOCH_DATA_KEY_FORMAT);
393
394 int expected_epoch = epoch ? 4 : 0;
395
396 /* Ensure that we are still on the initial key (our init_crypto_options
397 * unit test method iterates the initial key to 4) or that it is 0 when
398 * epoch is not in use
399 */
401
402 encrypt_one_packet(co, 1000);
403
404 /* either epoch key has been updated or warning is enabled */
405 if (epoch && !chachapoly)
406 {
408 }
409
411
412 if (!epoch)
413 {
414 /* Check always against the GCM usage limit here to see if that
415 * check works */
418 return;
419 }
420
421 /* Move to the end of the epoch data key send PID range, ChachaPoly
422 * should now also move to a new epoch data key */
424
425 encrypt_one_packet(co, 1000);
426 encrypt_one_packet(co, 1000);
427
430}
431
432
433static struct crypto_options
434init_crypto_options(const char *cipher, const char *auth, bool epoch, struct key2 *statickey)
435{
436 struct key2 key2 = { .n = 2 };
437
438 if (statickey)
439 {
440 /* Use chosen static key instead of random key when defined */
441 key2 = *statickey;
442 }
443 else
444 {
445 prng_bytes(key2.keys[0].cipher, sizeof(key2.keys[0].cipher));
446 prng_bytes(key2.keys[0].hmac, sizeof(key2.keys[0].hmac));
447 prng_bytes(key2.keys[1].cipher, sizeof(key2.keys[1].cipher));
448 prng_bytes(key2.keys[1].hmac, sizeof(key2.keys)[1].hmac);
449 }
450
451 struct crypto_options co = { 0 };
452
453 struct key_type kt = create_kt(cipher, auth, "ssl-test");
454
455 if (epoch)
456 {
457 struct epoch_key e1 = { .epoch = 1, .epoch_key = { 0 } };
458 memcpy(e1.epoch_key, key2.keys[0].cipher, sizeof(e1.epoch_key));
460 epoch_init_key_ctx(&co, &kt, &e1, &e1, 5);
461
462 /* Do a little of dancing for the epoch_send_key_iterate to test
463 * that this works too */
467 }
468 else
469 {
470 init_key_ctx_bi(&co.key_ctx_bi, &key2, KEY_DIRECTION_BIDIRECTIONAL, &kt, "unit-test-ssl");
471 }
472 packet_id_init(&co.packet_id, 5, 5, "UNITTEST", 0);
473 return co;
474}
475
476static void
483
484/* This adds a few more methods than strictly necessary but this allows
485 * us to see which exact test was run from the backtrace of the test
486 * when it fails */
487static void
489{
490 bool ischacha = !strcmp(cipher, "ChaCha20-Poly1305");
491
492 struct crypto_options co = init_crypto_options(cipher, "none", true, NULL);
494 check_aead_limits(&co, ischacha);
496}
497
498static void
499run_data_channel_with_cipher(const char *cipher, const char *auth)
500{
501 bool ischacha = !strcmp(cipher, "ChaCha20-Poly1305");
502 struct crypto_options co = init_crypto_options(cipher, auth, false, NULL);
504 check_aead_limits(&co, ischacha);
506}
507
508
509static void
511{
512 run_data_channel_with_cipher("AES-128-GCM", "none");
513}
514
515static void
520
521static void
523{
524 run_data_channel_with_cipher("AES-192-GCM", "none");
525}
526
527static void
532
533static void
535{
536 run_data_channel_with_cipher("AES-256-GCM", "none");
537}
538
539static void
544
545static void
547{
548 run_data_channel_with_cipher("AES-128-CBC", "SHA256");
549}
550
551static void
553{
554 run_data_channel_with_cipher("AES-192-CBC", "SHA256");
555}
556
557static void
559{
560 run_data_channel_with_cipher("AES-256-CBC", "SHA256");
561}
562
563static void
565{
566 if (!cipher_valid("ChaCha20-Poly1305"))
567 {
568 skip();
569 return;
570 }
571
572 run_data_channel_with_cipher("ChaCha20-Poly1305", "none");
573}
574
575static void
577{
578 if (!cipher_valid("ChaCha20-Poly1305"))
579 {
580 skip();
581 return;
582 }
583
584 run_data_channel_with_cipher_epoch("ChaCha20-Poly1305");
585}
586
587static void
589{
590 if (!cipher_valid("BF-CBC"))
591 {
592 skip();
593 return;
594 }
595 run_data_channel_with_cipher("BF-CBC", "SHA1");
596}
597
598
599static struct key2
601{
602 struct key2 key2 = { .n = 2 };
603
604 const uint8_t key[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1', '2',
605 '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F',
606 'G', 'H', 'j', 'k', 'u', 'c', 'h', 'e', 'n', 'l' };
607
608 static_assert(sizeof(key) == 32, "Size of key should be 32 bytes");
609
610 /* copy the key a few times to ensure to have the size we need for
611 * Statickey but XOR it to not repeat it */
612 uint8_t keydata[sizeof(key2.keys)];
613
614 for (size_t i = 0; i < sizeof(key2.keys); i++)
615 {
616 keydata[i] = (uint8_t)(key[i % sizeof(key)] ^ i);
617 }
618
619 ASSERT(memcpy(key2.keys[0].cipher, keydata, sizeof(key2.keys[0].cipher)));
620 ASSERT(memcpy(key2.keys[0].hmac, keydata + 64, sizeof(key2.keys[0].hmac)));
621 ASSERT(memcpy(key2.keys[1].cipher, keydata + 128, sizeof(key2.keys[1].cipher)));
622 ASSERT(memcpy(key2.keys[1].hmac, keydata + 192, sizeof(key2.keys)[1].hmac));
623
624 return key2;
625}
626
627static void
629{
630 struct key2 key2 = create_key();
631
632 struct crypto_options co = init_crypto_options("AES-256-GCM", "none", epoch, &key2);
633
634 struct gc_arena gc = gc_new();
635
636 /* initialise frame for the test */
637 struct frame frame;
639
641 struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
644 struct buffer buf = clear_buf();
645 void *buf_p;
646
647 /* init work */
649
650 now = 0;
651
652 /*
653 * Load src with known data.
654 */
655 ASSERT(buf_init(&src, 0));
656 const char *plaintext = "The quick little fox jumps over the bureaucratic hurdles";
657
659
660 /* copy source to input buf */
661 buf = work;
662 buf_p = buf_write_alloc(&buf, BLENZ(&src));
663 ASSERT(buf_p);
664 memcpy(buf_p, BPTR(&src), BLENZ(&src));
665
666 /* initialize work buffer with buf.headroom bytes of prepend capacity */
668
669 /* add packet opcode and peer id */
674
675 /* encrypt */
677
678 /* separate buffer in authenticated data and encrypted data */
679 const uint8_t *ad_start = BPTR(&buf);
680 buf_advance(&buf, 4);
681
682 if (epoch)
683 {
684 uint8_t packetid1[8] = { 0, 0x04, 0, 0, 0, 0, 0, 1 };
686 }
687 else
688 {
689 uint8_t packetid1[4] = { 0, 0, 0, 1 };
691 }
692
693 if (epoch)
694 {
696 const uint8_t exp_tag_epoch[16] = { 0x0f, 0xff, 0xf5, 0x91, 0x3d, 0x39, 0xd7, 0x5b,
697 0x18, 0x57, 0x3b, 0x57, 0x48, 0x58, 0x9a, 0x7d };
698
700 }
701 else
702 {
703 uint8_t *tag_location = BPTR(&buf) + 4;
704 const uint8_t exp_tag_noepoch[16] = { 0x1f, 0xdd, 0x90, 0x8f, 0x0e, 0x9d, 0xc2, 0x5e,
705 0x79, 0xd8, 0x32, 0x02, 0x0d, 0x58, 0xe7, 0x3f };
707 }
708
709 /* Check some bytes at the beginning of the encrypted part */
710 if (epoch)
711 {
712 const uint8_t bytesat14[6] = { 0x36, 0xaa, 0xb4, 0xd4, 0x9c, 0xe6 };
713 assert_memory_equal(BPTR(&buf) + 14, bytesat14, sizeof(bytesat14));
714 }
715 else
716 {
717 const uint8_t bytesat30[6] = { 0xa8, 0x2e, 0x6b, 0x17, 0x06, 0xd9 };
718 assert_memory_equal(BPTR(&buf) + 30, bytesat30, sizeof(bytesat30));
719 }
720
721 /* decrypt */
723
724 /* compare */
727
729 gc_free(&gc);
730}
731
732static void
737
738static void
743
744#if defined(ENABLE_CRYPTO_MBEDTLS)
745static openvpn_x509_cert_t *
746get_certificate(const char *cert_str)
747{
748 mbedtls_x509_crt *cert;
750 int ret = mbedtls_x509_crt_parse(cert, (const unsigned char *)cert_str,
751 strlen(cert_str) + 1);
752
754 return cert;
755}
756
757static void
759{
761 free(cert);
762}
763#else
764static openvpn_x509_cert_t *
766{
767 BIO *in = BIO_new_mem_buf((char *)cert_str, -1);
768 assert_non_null(in);
769 X509 *cert = PEM_read_bio_X509(in, NULL, NULL, NULL);
770 assert_non_null(cert);
771 BIO_free(in);
772 return cert;
773}
774
775static void
780#endif
781
782/* Generated with:
783 * openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -keyout - -noenc -sha256 -days 3650 \
784 * -subj '/CN=ovpn-test-secp384r1/O=OpenVPN Unit Test Example Corp./OU=Cert Details Dept.'
785 * -addext 'subjectAltName=DNS:unittest.example.com' -addext 'extendedKeyUsage=clientAuth' */
786static const char *cert_details_test_cert =
787 "-----BEGIN CERTIFICATE-----\n"
788 "MIICkzCCAhqgAwIBAgIUKDsZM+PApGdaD2QF9iYaxoFJAkowCgYIKoZIzj0EAwIw\n"
789 "ZTEcMBoGA1UEAwwTb3Zwbi10ZXN0LXNlY3AzODRyMTEoMCYGA1UECgwfT3BlblZQ\n"
790 "TiBVbml0IFRlc3QgRXhhbXBsZSBDb3JwLjEbMBkGA1UECwwSQ2VydCBEZXRhaWxz\n"
791 "IERlcHQuMB4XDTI2MDcwNzEwNTIxNloXDTM2MDcwNDEwNTIxNlowZTEcMBoGA1UE\n"
792 "AwwTb3Zwbi10ZXN0LXNlY3AzODRyMTEoMCYGA1UECgwfT3BlblZQTiBVbml0IFRl\n"
793 "c3QgRXhhbXBsZSBDb3JwLjEbMBkGA1UECwwSQ2VydCBEZXRhaWxzIERlcHQuMHYw\n"
794 "EAYHKoZIzj0CAQYFK4EEACIDYgAEOlKoQVk+wbBD6V/6kg+/oHfqF0Dq08LlCL+B\n"
795 "om4RhutG99QDrow251Ps+Ds/7LQYYRA8+hHyEFrmGM+j2o6KhS5K2uA6dIZL4zLK\n"
796 "vl0NeF2M61Z8tt/IjrFZd+CrEANco4GKMIGHMB0GA1UdDgQWBBSEyG6m+QdWazeg\n"
797 "0CHN7q0edJlqMjAfBgNVHSMEGDAWgBSEyG6m+QdWazeg0CHN7q0edJlqMjAPBgNV\n"
798 "HRMBAf8EBTADAQH/MB8GA1UdEQQYMBaCFHVuaXR0ZXN0LmV4YW1wbGUuY29tMBMG\n"
799 "A1UdJQQMMAoGCCsGAQUFBwMCMAoGCCqGSM49BAMCA2cAMGQCMCyK7aQcyKGW8BWQ\n"
800 "UOYqbJUJZJcviP6ACgJRzK6pgkqt9gY0E0Tb00Qh6D5dBV5i3wIwCMhSgpVJxDrc\n"
801 "pRfligoK8bmv4HEgnV6BDeoDYd41WVMpE9u1issQDHY0SnWC7d9q\n"
802 "-----END CERTIFICATE-----\n";
803const char *const cert_details_cname = "ovpn-test-secp384r1";
804const char *const cert_details_org = "OpenVPN Unit Test Example Corp.";
805const char *const cert_details_org_unit = "Cert Details Dept.";
806const char *const cert_details_serial_number = "229677570263950905252266749734450551528150860362";
807const char *const cert_details_serial_number_hex = "0x283B1933E3C0A4675A0F6405F6261AC68149024A";
808
809void
811{
813 struct gc_arena gc = gc_new();
814
815 const char *fp = backend_x509_get_serial_hex(cert, &gc);
816
817 /* we messed this up between TLS libraries. But let's at least notice in
818 * the future ...*/
819#if defined(ENABLE_CRYPTO_MBEDTLS)
820 assert_string_equal(fp, "28:3B:19:33:E3:C0:A4:67:5A:0F:64:05:F6:26:1A:C6:81:49:02:4A");
821#else
822 assert_string_equal(fp, "28:3b:19:33:e3:c0:a4:67:5a:0f:64:05:f6:26:1a:c6:81:49:02:4a");
823#endif
824
825 const char *sn = backend_x509_get_serial(cert, &gc);
826 assert_string_equal(sn, cert_details_serial_number);
827
828 char username[TLS_USERNAME_LEN + 1] = { 0 }; /* null-terminated */
829
830 int ret = backend_x509_get_username(username, sizeof(username), "CN", cert);
831
832 assert_string_equal(username, cert_details_cname);
833 assert_int_equal(ret, SUCCESS);
834
835 ret = backend_x509_get_username(username, sizeof(username), "serialNumber", cert);
836 assert_int_equal(ret, SUCCESS);
837 assert_string_equal(username, cert_details_serial_number_hex);
838
839 ret = backend_x509_get_username(username, sizeof(username), "O", cert);
840
841 assert_string_equal(username, cert_details_org);
842 assert_int_equal(ret, SUCCESS);
843
844 ret = backend_x509_get_username(username, sizeof(username), "OU", cert);
845
846 assert_string_equal(username, cert_details_org_unit);
847 assert_int_equal(ret, SUCCESS);
848
849 /* Check that FAILURE is returned if a field does not exist. */
850 ret = backend_x509_get_username(username, sizeof(username), "SN", cert);
851 assert_int_equal(ret, FAILURE);
852
853 /* Check that FAILURE is returned for invalid field names. */
854 ret = backend_x509_get_username(username, sizeof(username), "invalidField", cert);
855 assert_int_equal(ret, FAILURE);
856
857 /* Check that FAILURE is returned if the output buffer is too small. Do this separately
858 * for a subject field and for the serial number, because these are different code paths.
859 *
860 * First case: Can't fit all characters. */
861 ret = backend_x509_get_username(username, strlen(cert_details_cname) / 2, "CN", cert);
862 assert_int_equal(ret, FAILURE);
863 ret = backend_x509_get_username(username, strlen(cert_details_serial_number_hex) / 2, "serialNumber", cert);
864 assert_int_equal(ret, FAILURE);
865
866 /* Second case: Can fit the characters but not the terminating '\0'. */
867 ret = backend_x509_get_username(username, strlen(cert_details_cname), "CN", cert);
868 assert_int_equal(ret, FAILURE);
869 ret = backend_x509_get_username(username, strlen(cert_details_serial_number_hex), "serialNumber", cert);
870 assert_int_equal(ret, FAILURE);
871
872 gc_free(&gc);
873 free_certificate(cert);
874}
875
876void
878{
879 const char *peer_info_normal =
880 "IV_VER=2.6_git\nIV_PLAT=mac\nIV_TCPNL=1\nIV_NCP=2\n"
881 "IV_CIPHERS=AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305\n"
882 "IV_PROTO=94\nIV_LZO_STUB=1\nIV_COMP_STUB=1\nP=78\nIV_COMP_STUBv2=1\n"
883 "IV_SSL=OpenSSL_3.0.5_5_Jul_2022\nIV_LZ4v2=1";
884
885 const char *empty = "";
886 const char *invalid_proto = "IV_PROTO=seven\nIV_SSL=7\nP=300\nID=xyz";
887 const char *test_prefix = "UV_IV_PROTO=773\nNP=112\nPD=8\n";
888
889
890 assert_int_equal(extract_iv_proto(peer_info_normal), 94);
891 assert_int_equal(extract_iv_proto(empty), 0);
892 assert_int_equal(extract_iv_proto(invalid_proto), 0);
893 /* This should not pick up the UV_IV_PROTO that has the extra prefix */
894 assert_int_equal(extract_iv_proto(test_prefix), 0);
895
896 assert_int_equal(peer_info_extract_uint(peer_info_normal, "IV_COMP_STUB="), 1);
897 assert_int_equal(peer_info_extract_int(empty, "IV_COMP_STUB=", "%d", 0xfe0d0d), 0xfe0d0d);
898 assert_int_equal(peer_info_extract_uint(invalid_proto, "IV_COMP_STUB="), 0);
899
900 assert_int_equal(peer_info_extract_int(test_prefix, "NP=", "%d", 23), 112);
901 assert_int_equal(peer_info_extract_uint(test_prefix, "PD="), 8);
902 assert_int_equal(peer_info_extract_int(test_prefix, "P=", "%x", 0xfe0d0d), 0xfe0d0d);
903 assert_int_equal(peer_info_extract_uint(peer_info_normal, "P="), 78);
904 assert_int_equal(peer_info_extract_uint(test_prefix, "UV_IV_PROTO="), 773);
905
906 struct gc_arena gc = gc_new();
907
908 const char *peer_ciphers = extract_var_peer_info(peer_info_normal, "IV_CIPHERS=", &gc);
909 assert_string_equal(peer_ciphers, "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305");
910
911 /* with the extra = this should not extract anything */
912 const char *proto = extract_var_peer_info(peer_info_normal, "IV_PROTO==", &gc);
913 assert_null(proto);
914
915 proto = extract_var_peer_info(peer_info_normal, "IV_PROTO=", &gc);
916 assert_string_equal(proto, "94");
917
918
919 const char *double_eq_info = "FOO=7\nFOO==new";
920 const char *foo_eq = extract_var_peer_info(double_eq_info, "FOO=", &gc);
921 const char *foo = extract_var_peer_info(double_eq_info, "FOO", &gc);
922 const char *foo_2eq = extract_var_peer_info(double_eq_info, "FOO==", &gc);
923
924 assert_string_equal(foo, "=7");
925 assert_string_equal(foo_eq, "7");
926 assert_string_equal(foo_2eq, "new");
927
928 assert_int_equal(extract_asymmetric_peer_id(double_eq_info), MAX_PEER_ID);
929 assert_int_equal(extract_asymmetric_peer_id(peer_info_normal), MAX_PEER_ID);
930 assert_int_equal(extract_asymmetric_peer_id(invalid_proto), MAX_PEER_ID);
931 assert_int_equal(extract_asymmetric_peer_id("ID=f7"), 0xf7);
932 assert_int_equal(extract_asymmetric_peer_id("X=foo\nID=12ab"), 0x12ab);
933 assert_int_equal(extract_asymmetric_peer_id("X=foo\nID=34dd\nY=bar"), 0x34dd);
934 assert_int_equal(extract_asymmetric_peer_id("X=foo\nID=12345678"), MAX_PEER_ID);
935
936 gc_free(&gc);
937}
938
939int
940main(void)
941{
943
944 const struct CMUnitTest tests[] = {
945 cmocka_unit_test(crypto_pem_encode_certificate),
946 cmocka_unit_test(test_load_certificate_and_key),
947 cmocka_unit_test(test_load_certificate_and_key_uri),
959 cmocka_unit_test(test_data_channel_roundtrip_bf_cbc),
962 cmocka_unit_test(crypto_test_print_cert_details),
963 cmocka_unit_test(ssl_test_extract_peer_info)
964
965 };
966
967#if defined(ENABLE_CRYPTO_OPENSSL)
968 tls_init_lib();
969#endif
970
971 int ret = cmocka_run_group_tests_name("ssl tests", tests, init, cleanup);
972
973#if defined(ENABLE_CRYPTO_OPENSSL)
974 tls_free_lib();
975#endif
976
977 return ret;
978}
bool buf_printf(struct buffer *buf, const char *format,...)
printf-style append to a buffer with overflow check.
Definition buffer.c:226
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Allocate a buffer of the given size under garbage collection.
Definition buffer.c:77
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Modifies a string in place by replacing certain classes of characters of it with a specified characte...
Definition buffer.c:1005
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:1356
Buffer management functions and garbage collection.
#define BEND(buf)
Return a pointer one past the end of the buffer content.
Definition buffer.h:141
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:151
static struct buffer clear_buf(void)
Return an empty, undefined struct buffer (all fields zero).
Definition buffer.h:376
#define CC_ANY
any character
Definition buffer.h:1636
#define BPTR(buf)
Return a pointer to the start of the buffer content.
Definition buffer.h:139
static uint8_t * buf_write_alloc(struct buffer *buf, size_t size)
Reserve space at the end of a buffer for writing.
Definition buffer.h:1148
static bool buf_advance(struct buffer *buf, ssize_t size)
Advance the content start of a buffer, consuming bytes from the front.
Definition buffer.h:1124
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Append data to a buffer.
Definition buffer.h:1198
#define CC_BACKSLASH
backslash
Definition buffer.h:1653
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Append a uint8_t to a buffer.
Definition buffer.h:1242
#define BLEN(buf)
Return the length of the buffer content in bytes.
Definition buffer.h:145
#define BLENZ(buf)
Return the length of the buffer content as a size_t.
Definition buffer.h:147
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1912
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
Definition buffer.h:1974
#define buf_init(buf, offset)
Definition buffer.h:356
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1896
void free_key_ctx_bi(struct key_ctx_bi *ctx)
Definition crypto.c:1100
void prng_bytes(uint8_t *output, int len)
Definition crypto.c:1729
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:1062
Data Channel Cryptography Module.
#define CO_EPOCH_DATA_KEY_FORMAT
Bit-flag indicating the epoch the data format.
Definition crypto.h:379
#define KEY_DIRECTION_BIDIRECTIONAL
Definition crypto.h:231
static bool aead_usage_limit_reached(const uint64_t limit, const struct key_ctx *key_ctx, int64_t higest_pid)
Checks if the usage limit for an AEAD cipher is reached.
Definition crypto.h:765
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:686
static bool cipher_valid(const char *ciphername)
Returns if the cipher is valid, based on the given cipher name.
#define OPENVPN_AEAD_TAG_LENGTH
void free_epoch_key_ctx(struct crypto_options *co)
Frees the extra data structures used by epoch keys in crypto_options.
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_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.
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:329
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:779
#define RELIABLE_ACK_SIZE
The maximum number of packet IDs \ waiting to be acknowledged which can \ be stored in one reliable_a...
Definition reliable.h:43
#define ACK_SIZE(n)
Definition reliable.h:70
@ write
#define BUF_SIZE(f)
Definition mtu.h:188
#define ASSERT(x)
Definition error.h:219
#define MAX_PEER_ID
Definition openvpn.h:550
time_t now
Definition otime.c:33
static void update_time(void)
Definition otime.h:84
void packet_id_init(struct packet_id *p, int seq_backtrack, int time_backtrack, const char *name, int unit)
Definition packet_id.c:96
void packet_id_free(struct packet_id *p)
Definition packet_id.c:126
#define PACKET_ID_EPOCH_MAX
Definition packet_id.h:47
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:540
const char * platform_get_tmp_dir(void)
Get a directory for temporary files.
Definition platform.c:588
static char * auth_challenge
Definition ssl.c:284
Control Channel SSL/Data channel negotiation module.
Control Channel SSL library backend module.
void tls_ctx_free(struct tls_root_ctx *ctx)
Frees the library-specific TLSv1 context.
int tls_ctx_load_priv_file(struct tls_root_ctx *ctx, const char *priv_key_file, bool priv_key_file_inline)
Load private key file into the given TLS context.
void tls_free_lib(void)
Free any global SSL library-specific data structures.
Definition ssl_openssl.c:98
void tls_init_lib(void)
Perform any static initialisation necessary by the library.
Definition ssl_openssl.c:91
void tls_ctx_new(struct tls_root_ctx *ctx)
Initialise a library-specific TLS context.
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.
char * extract_var_peer_info(const char *peer_info, const char *var, struct gc_arena *gc)
Extracts a variable from peer info, the returned string will be allocated using the supplied gc_arena...
Definition ssl_util.c:63
unsigned int peer_info_extract_int(const char *peer_info, const char *field, const char *format, unsigned int default_value)
Extracts the named integer variable and returns its value or default_value if it cannot be extracted.
Definition ssl_util.c:91
uint32_t extract_asymmetric_peer_id(const char *peer_info)
Extracts the ID variable and returns its value or MAX_PEER_ID if it cannot be extracted.
Definition ssl_util.c:115
unsigned int peer_info_extract_uint(const char *peer_info, const char *field)
Extracts the named integer variable and returns its value or 0 if it cannot be extracted.
Definition ssl_util.c:109
SSL utility functions.
static unsigned int extract_iv_proto(const char *peer_info)
Extracts the IV_PROTO variable and returns its value or 0 if it cannot be extracted.
Definition ssl_util.h:77
Control Channel Verification Module.
#define TLS_USERNAME_LEN
Maximum length of common name.
Definition ssl_verify.h:54
Control Channel Verification Module library-specific backend interface.
result_t backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
char * backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc)
char * backend_x509_get_serial(openvpn_x509_cert_t *cert, struct gc_arena *gc)
result_t backend_x509_get_username(char *common_name, size_t cn_len, char *x509_username_field, openvpn_x509_cert_t *peer_cert)
@ FAILURE
@ SUCCESS
mbedtls_x509_crt openvpn_x509_cert_t
Wrapper structure for dynamically allocated memory.
Definition buffer.h:71
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:76
Security parameter state for processing data channel packets.
Definition crypto.h:293
unsigned int flags
Bit-flags determining behavior of security operation functions.
Definition crypto.h:386
struct key_ctx_bi key_ctx_bi
OpenSSL cipher and HMAC contexts for both sending and receiving directions.
Definition crypto.h:294
struct packet_id packet_id
Current packet ID state for both sending and receiving directions.
Definition crypto.h:333
uint8_t epoch_key[SHA256_DIGEST_LENGTH]
Definition crypto.h:193
uint16_t epoch
Definition crypto.h:194
Packet geometry parameters.
Definition mtu.h:113
int tun_mtu
the (user) configured tun-mtu.
Definition mtu.h:147
int payload_size
the maximum size that a payload that our buffers can hold from either tun device or network link.
Definition mtu.h:118
int headroom
the headroom in the buffer, this is choosen to allow all potential header to be added before the pack...
Definition mtu.h:124
struct frame::@8 buf
int tailroom
the tailroom in the buffer.
Definition mtu.h:128
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:127
Container for bidirectional cipher and HMAC key material.
Definition crypto.h:240
int n
The number of key objects stored in the key2.keys array.
Definition crypto.h:241
struct key keys[2]
Two unidirectional sets of key material.
Definition crypto.h:243
struct key_ctx encrypt
Cipher and/or HMAC contexts for sending direction.
Definition crypto.h:281
uint16_t epoch
OpenVPN data channel epoch, this variable holds the epoch number this key belongs to.
Definition crypto.h:228
uint64_t plaintext_blocks
Counter for the number of plaintext block encrypted using this cipher with the current key in number ...
Definition crypto.h:222
const char * cipher
const name of the cipher
Definition crypto.h:142
Container for unidirectional cipher and HMAC key material.
Definition crypto.h:152
uint8_t cipher[MAX_CIPHER_KEY_LENGTH]
Key material for cipher operations.
Definition crypto.h:153
uint8_t hmac[MAX_HMAC_KEY_LENGTH]
Key material for HMAC operations.
Definition crypto.h:155
uint64_t id
Definition packet_id.h:153
struct packet_id_send send
Definition packet_id.h:200
Structure that wraps the TLS context.
SSL_CTX * ctx
Definition ssl_openssl.h:41
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:61
static const char * cert_details_test_cert
Definition test_ssl.c:786
void crypto_test_print_cert_details(void **state)
Definition test_ssl.c:810
static void test_data_channel_roundtrip_aes_192_cbc(void **state)
Definition test_ssl.c:552
static void test_load_certificate_and_key_uri(void **state)
Definition test_ssl.c:214
const char * certfile
Definition test_ssl.c:123
bool get_user_pass_cr(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags, const char *auth_challenge)
Retrieves the user credentials from various sources depending on the flags.
Definition test_ssl.c:79
static openvpn_x509_cert_t * get_certificate(const char *cert_str)
Definition test_ssl.c:765
static void test_data_channel_roundtrip_aes_192_gcm_epoch(void **state)
Definition test_ssl.c:528
const char *const cert_details_org
Definition test_ssl.c:804
static void encrypt_one_packet(struct crypto_options *co, int len)
Definition test_ssl.c:339
void ssl_test_extract_peer_info(void **state)
Definition test_ssl.c:877
static void test_data_channel_roundtrip_aes_256_cbc(void **state)
Definition test_ssl.c:558
static void test_load_certificate_and_key(void **state)
Definition test_ssl.c:192
static void test_data_channel_known_vectors_run(bool epoch)
Definition test_ssl.c:628
static struct key2 create_key(void)
Definition test_ssl.c:600
struct gc_arena gc
Definition test_ssl.c:122
void purge_user_pass(struct user_pass *up, bool force)
Definition test_ssl.c:85
static void check_aead_limits(struct crypto_options *co, bool chachapoly)
Definition test_ssl.c:383
const char * strerror_win32(DWORD errnum, struct gc_arena *gc)
Definition test_ssl.c:61
static const char *const unittest_cert
Definition test_ssl.c:96
static void run_data_channel_with_cipher_epoch(const char *cipher)
Definition test_ssl.c:488
const char *const cert_details_serial_number
Definition test_ssl.c:806
static int cleanup(void **state)
Definition test_ssl.c:152
static void do_data_channel_round_trip(struct crypto_options *co)
Definition test_ssl.c:283
static void test_data_channel_roundtrip_aes_128_gcm_epoch(void **state)
Definition test_ssl.c:516
static void crypto_pem_encode_certificate(void **state)
Definition test_ssl.c:162
static void test_data_channel_roundtrip_aes_128_gcm(void **state)
Definition test_ssl.c:510
int main(void)
Definition test_ssl.c:940
static void test_data_channel_roundtrip_aes_192_gcm(void **state)
Definition test_ssl.c:522
void throw_signal(const int signum)
Throw a hard signal.
Definition test_ssl.c:67
const char * keyfile
Definition test_ssl.c:124
static void init_frame_parameters(struct frame *frame)
Definition test_ssl.c:253
static void test_data_channel_roundtrip_bf_cbc(void **state)
Definition test_ssl.c:588
static void test_data_channel_roundtrip_chacha20_poly1305(void **state)
Definition test_ssl.c:564
struct signal_info siginfo_static
Definition test_ssl.c:58
static void uninit_crypto_options(struct crypto_options *co)
Definition test_ssl.c:477
static void test_data_channel_roundtrip_aes_256_gcm(void **state)
Definition test_ssl.c:534
const char *const cert_details_cname
Definition test_ssl.c:803
static void test_data_channel_known_vectors_epoch(void **state)
Definition test_ssl.c:733
const char *const cert_details_serial_number_hex
Definition test_ssl.c:807
static void test_data_channel_roundtrip_chacha20_poly1305_epoch(void **state)
Definition test_ssl.c:576
static const char *const unittest_key
Definition test_ssl.c:111
static struct @32 global_state
static void test_data_channel_roundtrip_aes_256_gcm_epoch(void **state)
Definition test_ssl.c:540
static int init(void **state)
Definition test_ssl.c:128
static void free_certificate(openvpn_x509_cert_t *cert)
Definition test_ssl.c:776
static void test_data_channel_roundtrip_aes_128_cbc(void **state)
Definition test_ssl.c:546
static struct crypto_options init_crypto_options(const char *cipher, const char *auth, bool epoch, struct key2 *statickey)
Definition test_ssl.c:434
const char *const cert_details_org_unit
Definition test_ssl.c:805
static void run_data_channel_with_cipher(const char *cipher, const char *auth)
Definition test_ssl.c:499
static void test_data_channel_known_vectors_shortpktid(void **state)
Definition test_ssl.c:739