]> git.ipfire.org Git - thirdparty/openvpn.git/blame - tests/unit_tests/openvpn/test_ncp.c
The Great Reformatting of 2022
[thirdparty/openvpn.git] / tests / unit_tests / openvpn / test_ncp.c
CommitLineData
1828f9c1
AS
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 *
1800d77e 8 * Copyright (C) 2019-2022 Arne Schwabe <arne@rfc2549.org>
1828f9c1
AS
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#elif defined(_MSC_VER)
27#include "config-msvc.h"
28#endif
29
30#include "syshead.h"
31
32#include <stdio.h>
1828f9c1
AS
33#include <stdlib.h>
34#include <stdarg.h>
35#include <string.h>
36#include <setjmp.h>
37#include <cmocka.h>
38
39#include "ssl_ncp.c"
40
41/* Defines for use in the tests and the mock parse_line() */
42
43const char *bf_chacha = "BF-CBC:CHACHA20-POLY1305";
c07f95f3 44const char *aes_chacha = "AES-128-CBC:CHACHA20-POLY1305";
1828f9c1
AS
45const char *aes_ciphers = "AES-256-GCM:AES-128-GCM";
46
8c72d798
AS
47
48/* Define this function here as dummy since including the ssl_*.c files
49 * leads to having to include even more unrelated code */
50bool
51key_state_export_keying_material(struct tls_session *session,
abe49856 52 const char *label, size_t label_size,
8c72d798
AS
53 void *ekm, size_t ekm_size)
54{
55 ASSERT(0);
56}
57
1828f9c1
AS
58static void
59test_check_ncp_ciphers_list(void **state)
60{
be453156 61 struct gc_arena gc = gc_new();
ce2954a0
AS
62 bool have_chacha = cipher_valid("CHACHA20-POLY1305");
63 bool have_blowfish = cipher_valid("BF-CBC");
1828f9c1 64
c018fc00
AS
65 assert_string_equal(mutate_ncp_cipher_list("none", &gc), "none");
66 assert_string_equal(mutate_ncp_cipher_list("AES-256-GCM:none", &gc),
67 "AES-256-GCM:none");
be453156
AS
68
69 assert_string_equal(mutate_ncp_cipher_list(aes_ciphers, &gc), aes_ciphers);
70
71 if (have_chacha)
c07f95f3
AS
72 {
73 assert_string_equal(mutate_ncp_cipher_list(aes_chacha, &gc), aes_chacha);
74 }
75
76 if (have_chacha && have_blowfish)
be453156
AS
77 {
78 assert_string_equal(mutate_ncp_cipher_list(bf_chacha, &gc), bf_chacha);
79 assert_string_equal(mutate_ncp_cipher_list("BF-CBC:CHACHA20-POLY1305", &gc),
80 bf_chacha);
81 }
82 else
83 {
84 assert_ptr_equal(mutate_ncp_cipher_list(bf_chacha, &gc), NULL);
85 }
86
76604450
AS
87 /* Check that optional ciphers work */
88 assert_string_equal(mutate_ncp_cipher_list("AES-256-GCM:?vollbit:AES-128-GCM", &gc),
89 aes_ciphers);
90
91 /* Check that optional ciphers work */
92 assert_string_equal(mutate_ncp_cipher_list("?AES-256-GCM:?AES-128-GCM", &gc),
93 aes_ciphers);
94
95 /* All unsupported should still yield an empty list */
96 assert_ptr_equal(mutate_ncp_cipher_list("?kugelfisch:?grasshopper", &gc), NULL);
97
86843385
AS
98 /* If the last is optional, previous invalid ciphers should be ignored */
99 assert_ptr_equal(mutate_ncp_cipher_list("Vollbit:Littlebit:AES-256-CBC:BF-CBC:?nixbit", &gc), NULL);
100
be453156 101 /* For testing that with OpenSSL 1.1.0+ that also accepts ciphers in
da1574ef 102 * a different spelling the normalised cipher output is the same */
ce2954a0 103 bool have_chacha_mixed_case = cipher_valid("ChaCha20-Poly1305");
be453156
AS
104 if (have_chacha_mixed_case)
105 {
c07f95f3
AS
106 assert_string_equal(mutate_ncp_cipher_list("AES-128-CBC:ChaCha20-Poly1305", &gc),
107 aes_chacha);
be453156
AS
108 }
109
110 assert_ptr_equal(mutate_ncp_cipher_list("vollbit", &gc), NULL);
111 assert_ptr_equal(mutate_ncp_cipher_list("AES-256-GCM:vollbit", &gc), NULL);
112 assert_ptr_equal(mutate_ncp_cipher_list("", &gc), NULL);
113
114 assert_ptr_equal(mutate_ncp_cipher_list(
115 "ChaCha20-Poly1305:ChaCha20-Poly1305:ChaCha20-Poly1305:"
116 "ChaCha20-Poly1305:ChaCha20-Poly1305:ChaCha20-Poly1305:"
117 "ChaCha20-Poly1305", &gc), NULL);
118
119#ifdef ENABLE_CRYPTO_OPENSSL
120 assert_string_equal(mutate_ncp_cipher_list("id-aes128-GCM:id-aes256-GCM",
121 &gc), "AES-128-GCM:AES-256-GCM");
122#else
0e075c0e
MF
123 if (have_blowfish)
124 {
125 assert_string_equal(mutate_ncp_cipher_list("BLOWFISH-CBC",
126 &gc), "BF-CBC");
127 }
be453156
AS
128#endif
129 gc_free(&gc);
1828f9c1
AS
130}
131
132static void
133test_extract_client_ciphers(void **state)
134{
135 struct gc_arena gc = gc_new();
136 const char *client_peer_info;
137 const char *peer_list;
138
139 client_peer_info = "foo=bar\nIV_foo=y\nIV_NCP=2";
140 peer_list = tls_peer_ncp_list(client_peer_info, &gc);
141 assert_string_equal(aes_ciphers,peer_list);
142 assert_true(tls_peer_supports_ncp(client_peer_info));
143
144 client_peer_info = "foo=bar\nIV_foo=y\nIV_NCP=2\nIV_CIPHERS=BF-CBC";
145 peer_list = tls_peer_ncp_list(client_peer_info, &gc);
146 assert_string_equal("BF-CBC", peer_list);
147 assert_true(tls_peer_supports_ncp(client_peer_info));
148
149 client_peer_info = "IV_NCP=2\nIV_CIPHERS=BF-CBC:FOO-BAR\nIV_BAR=7";
150 peer_list = tls_peer_ncp_list(client_peer_info, &gc);
151 assert_string_equal("BF-CBC:FOO-BAR", peer_list);
152 assert_true(tls_peer_supports_ncp(client_peer_info));
153
154 client_peer_info = "IV_CIPHERS=BF-CBC:FOO-BAR\nIV_BAR=7";
155 peer_list = tls_peer_ncp_list(client_peer_info, &gc);
156 assert_string_equal("BF-CBC:FOO-BAR", peer_list);
157 assert_true(tls_peer_supports_ncp(client_peer_info));
158
159 client_peer_info = "IV_YOLO=NO\nIV_BAR=7";
160 peer_list = tls_peer_ncp_list(client_peer_info, &gc);
161 assert_string_equal("", peer_list);
162 assert_false(tls_peer_supports_ncp(client_peer_info));
163
164 peer_list = tls_peer_ncp_list(NULL, &gc);
165 assert_string_equal("", peer_list);
166 assert_false(tls_peer_supports_ncp(client_peer_info));
167
168 gc_free(&gc);
169}
170
171static void
172test_poor_man(void **state)
173{
174 struct gc_arena gc = gc_new();
175 char *best_cipher;
176
be453156 177 const char *serverlist = "CHACHA20_POLY1305:AES-128-GCM";
c018fc00 178 const char *serverlistbfcbc = "CHACHA20_POLY1305:AES-128-GCM:BF-CBC:none";
1828f9c1 179
2c1d8c33
AS
180 best_cipher = ncp_get_best_cipher(serverlist,
181 "IV_YOLO=NO\nIV_BAR=7",
182 "BF-CBC", &gc);
183
184 assert_ptr_equal(best_cipher, NULL);
185
186
187 best_cipher = ncp_get_best_cipher(serverlistbfcbc,
1828f9c1
AS
188 "IV_YOLO=NO\nIV_BAR=7",
189 "BF-CBC", &gc);
190
191 assert_string_equal(best_cipher, "BF-CBC");
192
2c1d8c33
AS
193
194 best_cipher = ncp_get_best_cipher(serverlist,
1828f9c1
AS
195 "IV_NCP=1\nIV_BAR=7",
196 "AES-128-GCM", &gc);
197
198 assert_string_equal(best_cipher, "AES-128-GCM");
199
2c1d8c33 200 best_cipher = ncp_get_best_cipher(serverlist, NULL,
1828f9c1
AS
201 "AES-128-GCM", &gc);
202
203 assert_string_equal(best_cipher, "AES-128-GCM");
204
c018fc00
AS
205 best_cipher = ncp_get_best_cipher(serverlist, NULL,
206 "none", &gc);
207 assert_ptr_equal(best_cipher, NULL);
208
209 best_cipher = ncp_get_best_cipher(serverlistbfcbc, NULL,
210 "none", &gc);
211 assert_string_equal(best_cipher, "none");
212
2c1d8c33
AS
213 best_cipher = ncp_get_best_cipher(serverlist, NULL,NULL, &gc);
214 assert_ptr_equal(best_cipher, NULL);
215
1828f9c1
AS
216 gc_free(&gc);
217}
218
219
220static void
221test_ncp_best(void **state)
222{
223 struct gc_arena gc = gc_new();
224 char *best_cipher;
225
be453156 226 const char *serverlist = "CHACHA20_POLY1305:AES-128-GCM:AES-256-GCM";
1828f9c1 227
2c1d8c33 228 best_cipher = ncp_get_best_cipher(serverlist,
1828f9c1
AS
229 "IV_YOLO=NO\nIV_NCP=2\nIV_BAR=7",
230 "BF-CBC", &gc);
231
232 assert_string_equal(best_cipher, "AES-128-GCM");
233
234 /* Best cipher is in --cipher of client */
2c1d8c33 235 best_cipher = ncp_get_best_cipher(serverlist, "IV_NCP=2\nIV_BAR=7",
1828f9c1
AS
236 "CHACHA20_POLY1305", &gc);
237
238 assert_string_equal(best_cipher, "CHACHA20_POLY1305");
239
240 /* Best cipher is in --cipher of client */
2c1d8c33 241 best_cipher = ncp_get_best_cipher(serverlist, "IV_CIPHERS=AES-128-GCM",
1828f9c1
AS
242 "AES-256-CBC", &gc);
243
244
245 assert_string_equal(best_cipher, "AES-128-GCM");
246
247 /* IV_NCP=2 should be ignored if IV_CIPHERS is sent */
2c1d8c33 248 best_cipher = ncp_get_best_cipher(serverlist,
1828f9c1
AS
249 "IV_FOO=7\nIV_CIPHERS=AES-256-GCM\nIV_NCP=2",
250 "AES-256-CBC", &gc);
251
252 assert_string_equal(best_cipher, "AES-256-GCM");
253
254
255 gc_free(&gc);
256}
257
258
259
1828f9c1
AS
260const struct CMUnitTest ncp_tests[] = {
261 cmocka_unit_test(test_check_ncp_ciphers_list),
262 cmocka_unit_test(test_extract_client_ciphers),
263 cmocka_unit_test(test_poor_man),
264 cmocka_unit_test(test_ncp_best)
265};
266
267
be453156
AS
268int
269main(void)
1828f9c1
AS
270{
271#if defined(ENABLE_CRYPTO_OPENSSL)
272 OpenSSL_add_all_algorithms();
273#endif
274 return cmocka_run_group_tests(ncp_tests, NULL, NULL);
275}