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
183 struct buffer exported_pem = buffer_read_from_file(tmpfile, &gc);
184 assert_string_equal(BSTR(&exported_pem), unittest_cert);
185
186 tls_ctx_free(&ctx);
187 unlink(tmpfile);
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#ifdef _WIN32
232 const char *lead = "/";
233#else
234 const char *lead = "";
235#endif /* _WIN32 */
236 assert_true(buf_printf(&certuri, "file:%s%s", lead, certfile));
237 assert_true(buf_printf(&keyuri, "file:%s%s", lead, keyfile));
238
239 /* On Windows replace any '\' in path by '/' required for URI */
240#ifdef _WIN32
241 string_mod(BSTR(&certuri), CC_ANY, CC_BACKSLASH, '/');
242 string_mod(BSTR(&keyuri), CC_ANY, CC_BACKSLASH, '/');
243#endif /* _WIN32 */
244
245 tls_ctx_new(&ctx);
246 tls_ctx_load_cert_file(&ctx, BSTR(&certuri), false);
247 assert_int_equal(tls_ctx_load_priv_file(&ctx, BSTR(&keyuri), false), 0);
248 tls_ctx_free(&ctx);
249#endif /* HAVE_OPENSSL_STORE */
250}
251
252
253static void
255{
256 int overhead = 0;
257
258 /* tls-auth and tls-crypt */
259 overhead += 128;
260
261 /* TCP length field and opcode */
262 overhead += 3;
263
264 /* ACK array and remote SESSION ID (part of the ACK array) */
265 overhead += ACK_SIZE(RELIABLE_ACK_SIZE);
266
267 /* Previous OpenVPN version calculated the maximum size and buffer of a
268 * control frame depending on the overhead of the data channel frame
269 * overhead and limited its maximum size to 1250. Since control frames
270 * also need to fit into data channel buffer we have the same
271 * default of 1500 + 100 as data channel buffers have. Increasing
272 * control channel mtu beyond this limit also increases the data channel
273 * buffers */
274 int tls_mtu = 1500;
275 frame->buf.payload_size = tls_mtu + 100;
276
277 frame->buf.headroom = overhead;
278 frame->buf.tailroom = overhead;
279
280 frame->tun_mtu = tls_mtu;
281}
282
283static void
285{
286 struct gc_arena gc = gc_new();
287
288 /* initialise frame for the test */
289 struct frame frame;
291
292 struct buffer src = alloc_buf_gc(frame.buf.payload_size, &gc);
293 struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
294 struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
295 struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
296
297 /* init work */
299
300 update_time();
301
302 /* Test encryption, decryption for all packet sizes */
303 for (int i = 1; i <= frame.buf.payload_size; ++i)
304 {
305 /* msg(M_INFO, "TESTING ENCRYPT/DECRYPT of packet length=%d", i); */
306
307 /*
308 * Load src with random data.
309 */
310 ASSERT(buf_init(&src, 0));
311 ASSERT(i <= src.capacity);
312 src.len = i;
313 prng_bytes(BPTR(&src), BLEN(&src));
314
315 /* copy source to input buf */
316 struct buffer buf = work;
317 void *buf_p = buf_write_alloc(&buf, BLENZ(&src));
318 ASSERT(buf_p);
319 memcpy(buf_p, BPTR(&src), BLENZ(&src));
320
321 /* initialize work buffer with buf.headroom bytes of prepend capacity */
322 ASSERT(buf_init(&encrypt_workspace, frame.buf.headroom));
323
324 /* encrypt */
325 openvpn_encrypt(&buf, encrypt_workspace, co);
326
327 /* decrypt */
328 openvpn_decrypt(&buf, decrypt_workspace, co, &frame, BPTR(&buf));
329
330 /* compare */
331 assert_int_equal(buf.len, src.len);
332 assert_memory_equal(BPTR(&src), BPTR(&buf), i);
333 }
334 gc_free(&gc);
335}
336
337static void
339{
340 struct frame frame;
342
343 struct gc_arena gc = gc_new();
344 struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
345 struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
346 struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
347 struct buffer src = alloc_buf_gc(frame.buf.payload_size, &gc);
348 void *buf_p;
349
351
352 /*
353 * Load src with random data.
354 */
355 ASSERT(buf_init(&src, 0));
356 ASSERT(len <= src.capacity);
357 src.len = len;
358 prng_bytes(BPTR(&src), BLEN(&src));
359
360 /* copy source to input buf */
361 struct buffer buf = work;
362 buf_p = buf_write_alloc(&buf, BLENZ(&src));
363 ASSERT(buf_p);
364 memcpy(buf_p, BPTR(&src), BLENZ(&src));
365
366 ASSERT(buf_init(&encrypt_workspace, frame.buf.headroom));
367 openvpn_encrypt(&buf, encrypt_workspace, co);
368
369 /* decrypt */
370 openvpn_decrypt(&buf, decrypt_workspace, co, &frame, BPTR(&buf));
371
372 /* compare */
373 assert_int_equal(buf.len, src.len);
374 assert_memory_equal(BPTR(&src), BPTR(&buf), len);
375
376 gc_free(&gc);
377}
378
379
380static void
381check_aead_limits(struct crypto_options *co, bool chachapoly)
382{
383 /* Check that we correctly react when we have a nearing AEAD limits */
384
385 /* manually increase the send counter to be past
386 * the GCM usage limit */
387 co->key_ctx_bi.encrypt.plaintext_blocks = 0x1ull << 40;
388
389
390 bool epoch = (co->flags & CO_EPOCH_DATA_KEY_FORMAT);
391
392 int expected_epoch = epoch ? 4 : 0;
393
394 /* Ensure that we are still on the initial key (our init_crypto_options
395 * unit test method iterates the initial key to 4) or that it is 0 when
396 * epoch is not in use
397 */
398 assert_int_equal(co->key_ctx_bi.encrypt.epoch, expected_epoch);
399
400 encrypt_one_packet(co, 1000);
401
402 /* either epoch key has been updated or warning is enabled */
403 if (epoch && !chachapoly)
404 {
405 expected_epoch++;
406 }
407
408 assert_int_equal(co->key_ctx_bi.encrypt.epoch, expected_epoch);
409
410 if (!epoch)
411 {
412 /* Check always against the GCM usage limit here to see if that
413 * check works */
414 assert_true(
416 return;
417 }
418
419 /* Move to the end of the epoch data key send PID range, ChachaPoly
420 * should now also move to a new epoch data key */
422
423 encrypt_one_packet(co, 1000);
424 encrypt_one_packet(co, 1000);
425
426 expected_epoch++;
427 assert_int_equal(co->key_ctx_bi.encrypt.epoch, expected_epoch);
428}
429
430
431static struct crypto_options
432init_crypto_options(const char *cipher, const char *auth, bool epoch, struct key2 *statickey)
433{
434 struct key2 key2 = { .n = 2 };
435
436 if (statickey)
437 {
438 /* Use chosen static key instead of random key when defined */
439 key2 = *statickey;
440 }
441 else
442 {
443 prng_bytes(key2.keys[0].cipher, sizeof(key2.keys[0].cipher));
444 prng_bytes(key2.keys[0].hmac, sizeof(key2.keys[0].hmac));
445 prng_bytes(key2.keys[1].cipher, sizeof(key2.keys[1].cipher));
446 prng_bytes(key2.keys[1].hmac, sizeof(key2.keys)[1].hmac);
447 }
448
449 struct crypto_options co = { 0 };
450
451 struct key_type kt = create_kt(cipher, auth, "ssl-test");
452
453 if (epoch)
454 {
455 struct epoch_key e1 = { .epoch = 1, .epoch_key = { 0 } };
456 memcpy(e1.epoch_key, key2.keys[0].cipher, sizeof(e1.epoch_key));
458 epoch_init_key_ctx(&co, &kt, &e1, &e1, 5);
459
460 /* Do a little of dancing for the epoch_send_key_iterate to test
461 * that this works too */
465 }
466 else
467 {
468 init_key_ctx_bi(&co.key_ctx_bi, &key2, KEY_DIRECTION_BIDIRECTIONAL, &kt, "unit-test-ssl");
469 }
470 packet_id_init(&co.packet_id, 5, 5, "UNITTEST", 0);
471 return co;
472}
473
474static void
481
482/* This adds a few more methods than strictly necessary but this allows
483 * us to see which exact test was run from the backtrace of the test
484 * when it fails */
485static void
487{
488 bool ischacha = !strcmp(cipher, "ChaCha20-Poly1305");
489
490 struct crypto_options co = init_crypto_options(cipher, "none", true, NULL);
492 check_aead_limits(&co, ischacha);
494}
495
496static void
497run_data_channel_with_cipher(const char *cipher, const char *auth)
498{
499 bool ischacha = !strcmp(cipher, "ChaCha20-Poly1305");
500 struct crypto_options co = init_crypto_options(cipher, auth, false, NULL);
502 check_aead_limits(&co, ischacha);
504}
505
506
507static void
509{
510 run_data_channel_with_cipher("AES-128-GCM", "none");
511}
512
513static void
518
519static void
521{
522 run_data_channel_with_cipher("AES-192-GCM", "none");
523}
524
525static void
530
531static void
533{
534 run_data_channel_with_cipher("AES-256-GCM", "none");
535}
536
537static void
542
543static void
545{
546 run_data_channel_with_cipher("AES-128-CBC", "SHA256");
547}
548
549static void
551{
552 run_data_channel_with_cipher("AES-192-CBC", "SHA256");
553}
554
555static void
557{
558 run_data_channel_with_cipher("AES-256-CBC", "SHA256");
559}
560
561static void
563{
564 if (!cipher_valid("ChaCha20-Poly1305"))
565 {
566 skip();
567 return;
568 }
569
570 run_data_channel_with_cipher("ChaCha20-Poly1305", "none");
571}
572
573static void
575{
576 if (!cipher_valid("ChaCha20-Poly1305"))
577 {
578 skip();
579 return;
580 }
581
582 run_data_channel_with_cipher_epoch("ChaCha20-Poly1305");
583}
584
585static void
587{
588 if (!cipher_valid("BF-CBC"))
589 {
590 skip();
591 return;
592 }
593 run_data_channel_with_cipher("BF-CBC", "SHA1");
594}
595
596
597static struct key2
599{
600 struct key2 key2 = { .n = 2 };
601
602 const uint8_t key[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1', '2',
603 '3', '4', '5', '6', '7', 'A', 'B', 'C', 'D', 'E', 'F',
604 'G', 'H', 'j', 'k', 'u', 'c', 'h', 'e', 'n', 'l' };
605
606 static_assert(sizeof(key) == 32, "Size of key should be 32 bytes");
607
608 /* copy the key a few times to ensure to have the size we need for
609 * Statickey but XOR it to not repeat it */
610 uint8_t keydata[sizeof(key2.keys)];
611
612 for (size_t i = 0; i < sizeof(key2.keys); i++)
613 {
614 keydata[i] = (uint8_t)(key[i % sizeof(key)] ^ i);
615 }
616
617 ASSERT(memcpy(key2.keys[0].cipher, keydata, sizeof(key2.keys[0].cipher)));
618 ASSERT(memcpy(key2.keys[0].hmac, keydata + 64, sizeof(key2.keys[0].hmac)));
619 ASSERT(memcpy(key2.keys[1].cipher, keydata + 128, sizeof(key2.keys[1].cipher)));
620 ASSERT(memcpy(key2.keys[1].hmac, keydata + 192, sizeof(key2.keys)[1].hmac));
621
622 return key2;
623}
624
625static void
627{
628 struct key2 key2 = create_key();
629
630 struct crypto_options co = init_crypto_options("AES-256-GCM", "none", epoch, &key2);
631
632 struct gc_arena gc = gc_new();
633
634 /* initialise frame for the test */
635 struct frame frame;
637
638 struct buffer src = alloc_buf_gc(frame.buf.payload_size, &gc);
639 struct buffer work = alloc_buf_gc(BUF_SIZE(&frame), &gc);
640 struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
641 struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(&frame), &gc);
642 void *buf_p;
643
644 /* init work */
646
647 now = 0;
648
649 /*
650 * Load src with known data.
651 */
652 ASSERT(buf_init(&src, 0));
653 const char *plaintext = "The quick little fox jumps over the bureaucratic hurdles";
654
655 ASSERT(buf_write(&src, plaintext, strlen(plaintext)));
656
657 /* copy source to input buf */
658 struct buffer buf = work;
659 buf_p = buf_write_alloc(&buf, BLENZ(&src));
660 ASSERT(buf_p);
661 memcpy(buf_p, BPTR(&src), BLENZ(&src));
662
663 /* initialize work buffer with buf.headroom bytes of prepend capacity */
664 ASSERT(buf_init(&encrypt_workspace, frame.buf.headroom));
665
666 /* add packet opcode and peer id */
667 buf_write_u8(&encrypt_workspace, 7);
668 buf_write_u8(&encrypt_workspace, 0);
669 buf_write_u8(&encrypt_workspace, 0);
670 buf_write_u8(&encrypt_workspace, 23);
671
672 /* encrypt */
673 openvpn_encrypt(&buf, encrypt_workspace, &co);
674
675 /* separate buffer in authenticated data and encrypted data */
676 const uint8_t *ad_start = BPTR(&buf);
677 buf_advance(&buf, 4);
678
679 if (epoch)
680 {
681 uint8_t packetid1[8] = { 0, 0x04, 0, 0, 0, 0, 0, 1 };
682 assert_memory_equal(BPTR(&buf), packetid1, 8);
683 }
684 else
685 {
686 uint8_t packetid1[4] = { 0, 0, 0, 1 };
687 assert_memory_equal(BPTR(&buf), packetid1, 4);
688 }
689
690 if (epoch)
691 {
692 uint8_t *tag_location = BEND(&buf) - OPENVPN_AEAD_TAG_LENGTH;
693 const uint8_t exp_tag_epoch[16] = { 0x0f, 0xff, 0xf5, 0x91, 0x3d, 0x39, 0xd7, 0x5b,
694 0x18, 0x57, 0x3b, 0x57, 0x48, 0x58, 0x9a, 0x7d };
695
696 assert_memory_equal(tag_location, exp_tag_epoch, OPENVPN_AEAD_TAG_LENGTH);
697 }
698 else
699 {
700 uint8_t *tag_location = BPTR(&buf) + 4;
701 const uint8_t exp_tag_noepoch[16] = { 0x1f, 0xdd, 0x90, 0x8f, 0x0e, 0x9d, 0xc2, 0x5e,
702 0x79, 0xd8, 0x32, 0x02, 0x0d, 0x58, 0xe7, 0x3f };
703 assert_memory_equal(tag_location, exp_tag_noepoch, OPENVPN_AEAD_TAG_LENGTH);
704 }
705
706 /* Check some bytes at the beginning of the encrypted part */
707 if (epoch)
708 {
709 const uint8_t bytesat14[6] = { 0x36, 0xaa, 0xb4, 0xd4, 0x9c, 0xe6 };
710 assert_memory_equal(BPTR(&buf) + 14, bytesat14, sizeof(bytesat14));
711 }
712 else
713 {
714 const uint8_t bytesat30[6] = { 0xa8, 0x2e, 0x6b, 0x17, 0x06, 0xd9 };
715 assert_memory_equal(BPTR(&buf) + 30, bytesat30, sizeof(bytesat30));
716 }
717
718 /* decrypt */
719 openvpn_decrypt(&buf, decrypt_workspace, &co, &frame, ad_start);
720
721 /* compare */
722 assert_int_equal(buf.len, strlen(plaintext));
723 assert_memory_equal(BPTR(&buf), plaintext, strlen(plaintext));
724
726 gc_free(&gc);
727}
728
729static void
734
735static void
740
741#if defined(ENABLE_CRYPTO_MBEDTLS)
742static openvpn_x509_cert_t *
743get_certificate(const char *cert_str)
744{
745 mbedtls_x509_crt *cert;
746 ALLOC_OBJ_CLEAR(cert, mbedtls_x509_crt);
747 int ret = mbedtls_x509_crt_parse(cert, (const unsigned char *)cert_str,
748 strlen(cert_str) + 1);
749
750 assert_int_equal(ret, 0);
751 return cert;
752}
753
754static void
756{
757 mbedtls_x509_crt_free(cert);
758 free(cert);
759}
760#else
761static openvpn_x509_cert_t *
762get_certificate(const char *cert_str)
763{
764 BIO *in = BIO_new_mem_buf((char *)cert_str, -1);
765 assert_non_null(in);
766 X509 *cert = PEM_read_bio_X509(in, NULL, NULL, NULL);
767 assert_non_null(cert);
768 BIO_free(in);
769 return cert;
770}
771
772static void
774{
775 X509_free(cert);
776}
777#endif
778
779/* Generated with:
780 * openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -keyout - -noenc -sha256 -days 3650 \
781 * -subj '/CN=ovpn-test-secp384r1/O=OpenVPN Unit Test Example Corp./OU=Cert Details Dept.'
782 * -addext 'subjectAltName=DNS:unittest.example.com' -addext 'extendedKeyUsage=clientAuth' */
783static const char *cert_details_test_cert =
784 "-----BEGIN CERTIFICATE-----\n"
785 "MIICkzCCAhqgAwIBAgIUKDsZM+PApGdaD2QF9iYaxoFJAkowCgYIKoZIzj0EAwIw\n"
786 "ZTEcMBoGA1UEAwwTb3Zwbi10ZXN0LXNlY3AzODRyMTEoMCYGA1UECgwfT3BlblZQ\n"
787 "TiBVbml0IFRlc3QgRXhhbXBsZSBDb3JwLjEbMBkGA1UECwwSQ2VydCBEZXRhaWxz\n"
788 "IERlcHQuMB4XDTI2MDcwNzEwNTIxNloXDTM2MDcwNDEwNTIxNlowZTEcMBoGA1UE\n"
789 "AwwTb3Zwbi10ZXN0LXNlY3AzODRyMTEoMCYGA1UECgwfT3BlblZQTiBVbml0IFRl\n"
790 "c3QgRXhhbXBsZSBDb3JwLjEbMBkGA1UECwwSQ2VydCBEZXRhaWxzIERlcHQuMHYw\n"
791 "EAYHKoZIzj0CAQYFK4EEACIDYgAEOlKoQVk+wbBD6V/6kg+/oHfqF0Dq08LlCL+B\n"
792 "om4RhutG99QDrow251Ps+Ds/7LQYYRA8+hHyEFrmGM+j2o6KhS5K2uA6dIZL4zLK\n"
793 "vl0NeF2M61Z8tt/IjrFZd+CrEANco4GKMIGHMB0GA1UdDgQWBBSEyG6m+QdWazeg\n"
794 "0CHN7q0edJlqMjAfBgNVHSMEGDAWgBSEyG6m+QdWazeg0CHN7q0edJlqMjAPBgNV\n"
795 "HRMBAf8EBTADAQH/MB8GA1UdEQQYMBaCFHVuaXR0ZXN0LmV4YW1wbGUuY29tMBMG\n"
796 "A1UdJQQMMAoGCCsGAQUFBwMCMAoGCCqGSM49BAMCA2cAMGQCMCyK7aQcyKGW8BWQ\n"
797 "UOYqbJUJZJcviP6ACgJRzK6pgkqt9gY0E0Tb00Qh6D5dBV5i3wIwCMhSgpVJxDrc\n"
798 "pRfligoK8bmv4HEgnV6BDeoDYd41WVMpE9u1issQDHY0SnWC7d9q\n"
799 "-----END CERTIFICATE-----\n";
800const char *const cert_details_cname = "ovpn-test-secp384r1";
801const char *const cert_details_org = "OpenVPN Unit Test Example Corp.";
802const char *const cert_details_org_unit = "Cert Details Dept.";
803const char *const cert_details_serial_number = "229677570263950905252266749734450551528150860362";
804const char *const cert_details_serial_number_hex = "0x283B1933E3C0A4675A0F6405F6261AC68149024A";
805
806void
808{
810 struct gc_arena gc = gc_new();
811
812 const char *fp = backend_x509_get_serial_hex(cert, &gc);
813
814 /* we messed this up between TLS libraries. But let's at least notice in
815 * the future ...*/
816#if defined(ENABLE_CRYPTO_MBEDTLS)
817 assert_string_equal(fp, "28:3B:19:33:E3:C0:A4:67:5A:0F:64:05:F6:26:1A:C6:81:49:02:4A");
818#else
819 assert_string_equal(fp, "28:3b:19:33:e3:c0:a4:67:5a:0f:64:05:f6:26:1a:c6:81:49:02:4a");
820#endif
821
822 const char *sn = backend_x509_get_serial(cert, &gc);
823 assert_string_equal(sn, cert_details_serial_number);
824
825 char username[TLS_USERNAME_LEN + 1] = { 0 }; /* null-terminated */
826
827 int ret = backend_x509_get_username(username, sizeof(username), "CN", cert);
828
829 assert_string_equal(username, cert_details_cname);
830 assert_int_equal(ret, SUCCESS);
831
832 ret = backend_x509_get_username(username, sizeof(username), "serialNumber", cert);
833 assert_int_equal(ret, SUCCESS);
834 assert_string_equal(username, cert_details_serial_number_hex);
835
836 ret = backend_x509_get_username(username, sizeof(username), "O", cert);
837
838 assert_string_equal(username, cert_details_org);
839 assert_int_equal(ret, SUCCESS);
840
841 ret = backend_x509_get_username(username, sizeof(username), "OU", cert);
842
843 assert_string_equal(username, cert_details_org_unit);
844 assert_int_equal(ret, SUCCESS);
845
846 /* Check that FAILURE is returned if a field does not exist. */
847 ret = backend_x509_get_username(username, sizeof(username), "SN", cert);
848 assert_int_equal(ret, FAILURE);
849
850 /* Check that FAILURE is returned for invalid field names. */
851 ret = backend_x509_get_username(username, sizeof(username), "invalidField", cert);
852 assert_int_equal(ret, FAILURE);
853
854 /* Check that FAILURE is returned if the output buffer is too small. Do this separately
855 * for a subject field and for the serial number, because these are different code paths.
856 *
857 * First case: Can't fit all characters. */
858 ret = backend_x509_get_username(username, strlen(cert_details_cname) / 2, "CN", cert);
859 assert_int_equal(ret, FAILURE);
860 ret = backend_x509_get_username(username, strlen(cert_details_serial_number_hex) / 2, "serialNumber", cert);
861 assert_int_equal(ret, FAILURE);
862
863 /* Second case: Can fit the characters but not the terminating '\0'. */
864 ret = backend_x509_get_username(username, strlen(cert_details_cname), "CN", cert);
865 assert_int_equal(ret, FAILURE);
866 ret = backend_x509_get_username(username, strlen(cert_details_serial_number_hex), "serialNumber", cert);
867 assert_int_equal(ret, FAILURE);
868
869 gc_free(&gc);
870 free_certificate(cert);
871}
872
873/* Certificate with two CNs, "foo" and "bar".
874 *
875 * Generated with:
876 * openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:secp384r1 -subj "/CN=foo/CN=bar" \
877 * -noenc -out two_cns.crt -keyout two_cns.key
878 */
879static const char *cert_with_two_cns =
880 "-----BEGIN CERTIFICATE-----\n"
881 "MIIByTCCAVCgAwIBAgIUZuvd8Wfnq5jeRc3ohoJ/Vza54wQwCgYIKoZIzj0EAwIw\n"
882 "HDEMMAoGA1UEAwwDZm9vMQwwCgYDVQQDDANiYXIwHhcNMjYwODI4MTU1NjAwWhcN\n"
883 "MjYwOTI3MTU1NjAwWjAcMQwwCgYDVQQDDANmb28xDDAKBgNVBAMMA2JhcjB2MBAG\n"
884 "ByqGSM49AgEGBSuBBAAiA2IABERAfb210NOACy+QVYAu3EXrcGhTJpZDfhpDnE/h\n"
885 "PvPMWGWzqecTYdseArxZc0T/5Xma36IKCjGGsgN9ypZ5oQugQlB/NrVRCJIuHSGA\n"
886 "hGBWFvnUsqdNo765lGwVdBwhY6NTMFEwHQYDVR0OBBYEFPwnD+wK9R81Syk0qyTI\n"
887 "dFT/BNoJMB8GA1UdIwQYMBaAFPwnD+wK9R81Syk0qyTIdFT/BNoJMA8GA1UdEwEB\n"
888 "/wQFMAMBAf8wCgYIKoZIzj0EAwIDZwAwZAIwGxazGb6RRQtXzOWCPLRKId4e+E88\n"
889 "cwoCK3UwzEr8+Ddf54w5cEZC54f5J6AKFUJjAjBpT/JqF41uK57H+8i/16oZkBcm\n"
890 "OyQnlH8W/UzZo3/weTEBTcNW0iuCpIrS6im8pSk=\n"
891 "-----END CERTIFICATE-----\n";
892
893void
895{
896 /* When there are multiple fields of the same type in the certificate's subject, OpenVPN
897 * should extract the value of the last matching field. This is essentially arbitrary and there
898 * is no correct choice here, but this test exists to make sure that the behavior is consistent
899 * between different backends.
900 */
902
903 char username[TLS_USERNAME_LEN + 1] = { 0 };
904 assert_int_equal(backend_x509_get_username(username, sizeof(username), "CN", cert), SUCCESS);
905 assert_string_equal(username, "bar");
906 free_certificate(cert);
907}
908
909/* Certificate with a null-byte embedded in the CN.
910 *
911 * Generated with the following Python script:
912 *
913 * from cryptography import x509
914 * from cryptography.x509.oid import NameOID, ExtensionOID, ExtendedKeyUsageOID
915 * from cryptography.hazmat.primitives import hashes, serialization
916 * from cryptography.hazmat.primitives.asymmetric import ec
917 * import datetime
918 *
919 * private_key = ec.generate_private_key(ec.SECP384R1())
920 * now = datetime.datetime.now(datetime.timezone.utc)
921 * name = "with\x00null"
922 *
923 * cert = (x509.CertificateBuilder()
924 * .subject_name(x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, name)]))
925 * .issuer_name(x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, name)]))
926 * .public_key(private_key.public_key())
927 * .serial_number(x509.random_serial_number())
928 * .not_valid_before(now)
929 * .not_valid_after(now + datetime.timedelta(days=10 * 365))
930 * .sign(private_key, hashes.SHA256()))
931 *
932 * print(str(cert.public_bytes(serialization.Encoding.PEM), encoding='utf-8'))
933 **/
934static const char *cert_with_null =
935 "-----BEGIN CERTIFICATE-----\n"
936 "MIIBZTCB66ADAgECAhRLWdNRl+C20KKBG4QC9HFPWlOtBzAKBggqhkjOPQQDAjAU\n"
937 "MRIwEAYDVQQDDAl3aXRoAG51bGwwHhcNMjYwODI4MTQzMDA4WhcNMzYwODI1MTQz\n"
938 "MDA4WjAUMRIwEAYDVQQDDAl3aXRoAG51bGwwdjAQBgcqhkjOPQIBBgUrgQQAIgNi\n"
939 "AAT7PE+vJCBiB4CVHBcvJVF9n5n/dGQIn4C8HeYE8M2iXYCIRW5wg6/mlPaeiJY/\n"
940 "Ywh3pa8zhto1+aczbJKTvLgRwXn6N5vNpME1c5iWMzY0WHe1dJyVtoRBvkNvy5+k\n"
941 "GuEwCgYIKoZIzj0EAwIDaQAwZgIxAP2ekdQ8muG8Nv2o3PsBp0CqiaSNByGiP75i\n"
942 "k099bUFvHp/3LSp8Wf4JK2iWzc5h6gIxAINBGg2xjlmMgpXxROKA9qQqaM3d92Mp\n"
943 "EzZyRyPM3PGR83ZPbIaYDq8lCVxVlbYr/Q==\n"
944 "-----END CERTIFICATE-----\n";
945
946void
948{
950 struct gc_arena gc = gc_new();
951
952 /* Trying to get the subject as a whole should fail. */
953 assert_ptr_equal(x509_get_subject(cert, &gc), NULL);
954
955 /* Trying to extract the common name should fail. */
956 char username[TLS_USERNAME_LEN + 1] = { 0 };
957 assert_int_equal(backend_x509_get_username(username, sizeof(username), "CN", cert), FAILURE);
958 gc_free(&gc);
959 free_certificate(cert);
960}
961
962/* Cert with CN="name, O=InjectedOrg" and O=RealOrg.
963 *
964 * Generated with the following Python script:
965 *
966 * from cryptography import x509
967 * from cryptography.x509.oid import NameOID, ExtensionOID, ExtendedKeyUsageOID
968 * from cryptography.hazmat.primitives import hashes, serialization
969 * from cryptography.hazmat.primitives.asymmetric import ec
970 * import datetime
971 *
972 * private_key = ec.generate_private_key(ec.SECP384R1())
973 * now = datetime.datetime.now(datetime.timezone.utc)
974 * name = "name, O=InjectedOrg"
975 * org = "RealOrg"
976 *
977 * distinguished_name = x509.Name([
978 * x509.NameAttribute(NameOID.COMMON_NAME, name),
979 * x509.NameAttribute(NameOID.ORGANIZATION_NAME, org)
980 * ])
981 *
982 * cert = (x509.CertificateBuilder()
983 * .subject_name(distinguished_name)
984 * .issuer_name(distinguished_name)
985 * .public_key(private_key.public_key())
986 * .serial_number(x509.random_serial_number())
987 * .not_valid_before(now)
988 * .not_valid_after(now + datetime.timedelta(days=10 * 365))
989 * .sign(private_key, hashes.SHA256()))
990 *
991 * print(str(cert.public_bytes(serialization.Encoding.PEM), encoding='utf-8'))
992 */
993static const char *cert_with_rfc_2253_chars =
994 "-----BEGIN CERTIFICATE-----\n"
995 "MIIBnTCCASOgAwIBAgIUR1IGc6A800U14v/ykZNR21aVubowCgYIKoZIzj0EAwIw\n"
996 "MDEcMBoGA1UEAwwTbmFtZSwgTz1JbmplY3RlZE9yZzEQMA4GA1UECgwHUmVhbE9y\n"
997 "ZzAeFw0yNjA4MjgxNTQ3NDdaFw0zNjA4MjUxNTQ3NDdaMDAxHDAaBgNVBAMME25h\n"
998 "bWUsIE89SW5qZWN0ZWRPcmcxEDAOBgNVBAoMB1JlYWxPcmcwdjAQBgcqhkjOPQIB\n"
999 "BgUrgQQAIgNiAAR6zl9QPAbAnHWN//MRdowuhu0Sol6N+lqB/qk+D+2NHCd/t4H9\n"
1000 "cJlswUh6EPsmLxgfMYgO2QwClFWEFWvtXQs8BggoidY6i9pmAPhs8+9fmIyuNVpG\n"
1001 "3vUWZrUBRgylwaIwCgYIKoZIzj0EAwIDaAAwZQIwKzXmR8YPQZ1pratM9meVmGkH\n"
1002 "1rpHgV3U8oeg+jXmfVcZJTpDeDz4yBl4V3KBKT7HAjEAj2qkaTz7fiSwBKsxJQWH\n"
1003 "dQFPBCAYU9zZJvlNnEPtmHIwaD/qHXDeClr/HRItU3B9\n"
1004 "-----END CERTIFICATE-----\n";
1005
1006void
1008{
1010 struct gc_arena gc = gc_new();
1011
1012 char *subject = x509_get_subject(cert, &gc);
1013 assert_non_null(subject);
1014
1015 /* Mbed TLS escapes the '=' character but OpenSSL does not. */
1016 const char *expected_subject_openssl = "CN=name\\, O=InjectedOrg, O=RealOrg";
1017 const char *expected_subject_mbedtls = "CN=name\\, O\\=InjectedOrg, O=RealOrg";
1018
1019 assert_true(strcmp(subject, expected_subject_openssl) == 0 || strcmp(subject, expected_subject_mbedtls) == 0);
1020 gc_free(&gc);
1021 free_certificate(cert);
1022}
1023
1024void
1026{
1027 const char *peer_info_normal =
1028 "IV_VER=2.6_git\nIV_PLAT=mac\nIV_TCPNL=1\nIV_NCP=2\n"
1029 "IV_CIPHERS=AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305\n"
1030 "IV_PROTO=94\nIV_LZO_STUB=1\nIV_COMP_STUB=1\nP=78\nIV_COMP_STUBv2=1\n"
1031 "IV_SSL=OpenSSL_3.0.5_5_Jul_2022\nIV_LZ4v2=1";
1032
1033 const char *empty = "";
1034 const char *invalid_proto = "IV_PROTO=seven\nIV_SSL=7\nP=300\nID=xyz";
1035 const char *test_prefix = "UV_IV_PROTO=773\nNP=112\nPD=8\n";
1036
1037
1038 assert_int_equal(extract_iv_proto(peer_info_normal), 94);
1039 assert_int_equal(extract_iv_proto(empty), 0);
1040 assert_int_equal(extract_iv_proto(invalid_proto), 0);
1041 /* This should not pick up the UV_IV_PROTO that has the extra prefix */
1042 assert_int_equal(extract_iv_proto(test_prefix), 0);
1043
1044 assert_int_equal(peer_info_extract_uint(peer_info_normal, "IV_COMP_STUB="), 1);
1045 assert_int_equal(peer_info_extract_int(empty, "IV_COMP_STUB=", "%d", 0xfe0d0d), 0xfe0d0d);
1046 assert_int_equal(peer_info_extract_uint(invalid_proto, "IV_COMP_STUB="), 0);
1047
1048 assert_int_equal(peer_info_extract_int(test_prefix, "NP=", "%d", 23), 112);
1049 assert_int_equal(peer_info_extract_uint(test_prefix, "PD="), 8);
1050 assert_int_equal(peer_info_extract_int(test_prefix, "P=", "%x", 0xfe0d0d), 0xfe0d0d);
1051 assert_int_equal(peer_info_extract_uint(peer_info_normal, "P="), 78);
1052 assert_int_equal(peer_info_extract_uint(test_prefix, "UV_IV_PROTO="), 773);
1053
1054 struct gc_arena gc = gc_new();
1055
1056 const char *peer_ciphers = extract_var_peer_info(peer_info_normal, "IV_CIPHERS=", &gc);
1057 assert_string_equal(peer_ciphers, "AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305");
1058
1059 /* with the extra = this should not extract anything */
1060 const char *proto = extract_var_peer_info(peer_info_normal, "IV_PROTO==", &gc);
1061 assert_null(proto);
1062
1063 proto = extract_var_peer_info(peer_info_normal, "IV_PROTO=", &gc);
1064 assert_string_equal(proto, "94");
1065
1066
1067 const char *double_eq_info = "FOO=7\nFOO==new";
1068 const char *foo_eq = extract_var_peer_info(double_eq_info, "FOO=", &gc);
1069 const char *foo = extract_var_peer_info(double_eq_info, "FOO", &gc);
1070 const char *foo_2eq = extract_var_peer_info(double_eq_info, "FOO==", &gc);
1071
1072 assert_string_equal(foo, "=7");
1073 assert_string_equal(foo_eq, "7");
1074 assert_string_equal(foo_2eq, "new");
1075
1076 assert_int_equal(extract_asymmetric_peer_id(double_eq_info), MAX_PEER_ID);
1077 assert_int_equal(extract_asymmetric_peer_id(peer_info_normal), MAX_PEER_ID);
1078 assert_int_equal(extract_asymmetric_peer_id(invalid_proto), MAX_PEER_ID);
1079 assert_int_equal(extract_asymmetric_peer_id("ID=f7"), 0xf7);
1080 assert_int_equal(extract_asymmetric_peer_id("X=foo\nID=12ab"), 0x12ab);
1081 assert_int_equal(extract_asymmetric_peer_id("X=foo\nID=34dd\nY=bar"), 0x34dd);
1082 assert_int_equal(extract_asymmetric_peer_id("X=foo\nID=12345678"), MAX_PEER_ID);
1083
1084 gc_free(&gc);
1085}
1086
1087int
1088main(void)
1089{
1091
1092 const struct CMUnitTest tests[] = {
1093 cmocka_unit_test(crypto_pem_encode_certificate),
1094 cmocka_unit_test(test_load_certificate_and_key),
1095 cmocka_unit_test(test_load_certificate_and_key_uri),
1107 cmocka_unit_test(test_data_channel_roundtrip_bf_cbc),
1108 cmocka_unit_test(test_data_channel_known_vectors_epoch),
1110 cmocka_unit_test(crypto_test_print_cert_details),
1111 cmocka_unit_test(ssl_test_extract_last_matching_field),
1112 cmocka_unit_test(ssl_test_reject_null_in_cert_subject),
1114 cmocka_unit_test(ssl_test_extract_peer_info)
1115
1116 };
1117
1118#if defined(ENABLE_CRYPTO_OPENSSL)
1119 tls_init_lib();
1120#endif
1121
1122 int ret = cmocka_run_group_tests_name("ssl tests", tests, init, cleanup);
1123
1124#if defined(ENABLE_CRYPTO_OPENSSL)
1125 tls_free_lib();
1126#endif
1127
1128 return ret;
1129}
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:995
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:1346
Buffer management functions and garbage collection.
#define BEND(buf)
Return a pointer one past the end of the buffer content.
Definition buffer.h:143
#define BSTR(buf)
Return the buffer content pointer cast to char *.
Definition buffer.h:157
#define CC_ANY
any character
Definition buffer.h:1700
#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:1212
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:1188
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Append data to a buffer.
Definition buffer.h:1262
#define CC_BACKSLASH
backslash
Definition buffer.h:1717
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Append a uint8_t to a buffer.
Definition buffer.h:1306
#define BLEN(buf)
Return the length of the buffer content in bytes.
Definition buffer.h:151
#define BLENZ(buf)
Return the length of the buffer content as a size_t.
Definition buffer.h:153
static void gc_free(struct gc_arena *a)
Free all allocations in a garbage collection arena.
Definition buffer.h:1976
#define ALLOC_OBJ_CLEAR(dptr, type)
Allocate and zero-initialise memory for a single object of the given type.
Definition buffer.h:2038
#define buf_init(buf, offset)
Definition buffer.h:364
static struct gc_arena gc_new(void)
Allocate and return a new, empty garbage collection arena.
Definition buffer.h:1960
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:1727
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_ack s...
Definition reliable.h:43
#define ACK_SIZE(n)
Definition reliable.h:81
@ write
#define BUF_SIZE(f)
Definition mtu.h:188
#define ASSERT(x)
Definition error.h:221
#define MAX_PEER_ID
Definition openvpn.h:552
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:586
struct signal_info siginfo_static
Definition sig.c:44
static char * auth_challenge
Definition ssl.c:292
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 * x509_get_subject(openvpn_x509_cert_t *cert, struct gc_arena *gc)
Definition test_pkcs11.c:70
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 capacity
Size in bytes of memory allocated by malloc().
Definition buffer.h:72
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
Packet geometry parameters.
Definition mtu.h:113
int tun_mtu
the (user) configured tun-mtu.
Definition mtu.h:147
struct frame::@074234134026241341315172337061247271261307273127 buf
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
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
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 int cleanup(void **state)
static int init(void **state)
static const char * cert_details_test_cert
Definition test_ssl.c:783
void crypto_test_print_cert_details(void **state)
Definition test_ssl.c:807
static void test_data_channel_roundtrip_aes_192_cbc(void **state)
Definition test_ssl.c:550
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:762
static void test_data_channel_roundtrip_aes_192_gcm_epoch(void **state)
Definition test_ssl.c:526
const char *const cert_details_org
Definition test_ssl.c:801
static void encrypt_one_packet(struct crypto_options *co, int len)
Definition test_ssl.c:338
void ssl_test_extract_peer_info(void **state)
Definition test_ssl.c:1025
static void test_data_channel_roundtrip_aes_256_cbc(void **state)
Definition test_ssl.c:556
static void test_load_certificate_and_key(void **state)
Definition test_ssl.c:192
void ssl_test_extract_last_matching_field(void **state)
Definition test_ssl.c:894
static const char * cert_with_two_cns
Definition test_ssl.c:879
static void test_data_channel_known_vectors_run(bool epoch)
Definition test_ssl.c:626
static struct key2 create_key(void)
Definition test_ssl.c:598
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:381
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 struct @041167262151223363234312074372224332231333353344 global_state
static void run_data_channel_with_cipher_epoch(const char *cipher)
Definition test_ssl.c:486
const char *const cert_details_serial_number
Definition test_ssl.c:803
static const char * cert_with_null
Definition test_ssl.c:934
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:284
static void test_data_channel_roundtrip_aes_128_gcm_epoch(void **state)
Definition test_ssl.c:514
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:508
static const char * cert_with_rfc_2253_chars
Definition test_ssl.c:993
int main(void)
Definition test_ssl.c:1088
void ssl_test_escape_rfc_2253_chars_in_subject(void **state)
Definition test_ssl.c:1007
static void test_data_channel_roundtrip_aes_192_gcm(void **state)
Definition test_ssl.c:520
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:254
static void test_data_channel_roundtrip_bf_cbc(void **state)
Definition test_ssl.c:586
static void test_data_channel_roundtrip_chacha20_poly1305(void **state)
Definition test_ssl.c:562
void ssl_test_reject_null_in_cert_subject(void **state)
Definition test_ssl.c:947
static void uninit_crypto_options(struct crypto_options *co)
Definition test_ssl.c:475
static void test_data_channel_roundtrip_aes_256_gcm(void **state)
Definition test_ssl.c:532
const char *const cert_details_cname
Definition test_ssl.c:800
static void test_data_channel_known_vectors_epoch(void **state)
Definition test_ssl.c:730
const char *const cert_details_serial_number_hex
Definition test_ssl.c:804
static void test_data_channel_roundtrip_chacha20_poly1305_epoch(void **state)
Definition test_ssl.c:574
static const char *const unittest_key
Definition test_ssl.c:111
static void test_data_channel_roundtrip_aes_256_gcm_epoch(void **state)
Definition test_ssl.c:538
static int init(void **state)
Definition test_ssl.c:128
static void free_certificate(openvpn_x509_cert_t *cert)
Definition test_ssl.c:773
static void test_data_channel_roundtrip_aes_128_cbc(void **state)
Definition test_ssl.c:544
static struct crypto_options init_crypto_options(const char *cipher, const char *auth, bool epoch, struct key2 *statickey)
Definition test_ssl.c:432
const char *const cert_details_org_unit
Definition test_ssl.c:802
static void run_data_channel_with_cipher(const char *cipher, const char *auth)
Definition test_ssl.c:497
static void test_data_channel_known_vectors_shortpktid(void **state)
Definition test_ssl.c:736