OpenVPN
test_ncp.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) 2019 Arne Schwabe <arne@rfc2549.org>
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>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <string.h>
37 #include <setjmp.h>
38 #include <cmocka.h>
39 
40 #include "ssl_ncp.c"
41 
42 /* Defines for use in the tests and the mock parse_line() */
43 
44 const char *bf_chacha = "BF-CBC:CHACHA20-POLY1305";
45 const char *aes_ciphers = "AES-256-GCM:AES-128-GCM";
46 
47 static void
49 {
50  struct gc_arena gc = gc_new();
51  bool have_chacha = cipher_kt_get("CHACHA20-POLY1305");
52 
53  assert_string_equal(mutate_ncp_cipher_list("none", &gc), "none");
54  assert_string_equal(mutate_ncp_cipher_list("AES-256-GCM:none", &gc),
55  "AES-256-GCM:none");
56 
58 
59  if (have_chacha)
60  {
62  assert_string_equal(mutate_ncp_cipher_list("BF-CBC:CHACHA20-POLY1305", &gc),
63  bf_chacha);
64  }
65  else
66  {
68  }
69 
70  /* For testing that with OpenSSL 1.1.0+ that also accepts ciphers in
71  * a different spelling the normalised cipher output is the same */
72  bool have_chacha_mixed_case = cipher_kt_get("ChaCha20-Poly1305");
73  if (have_chacha_mixed_case)
74  {
75  assert_string_equal(mutate_ncp_cipher_list("BF-CBC:ChaCha20-Poly1305", &gc),
76  bf_chacha);
77  }
78 
79  assert_ptr_equal(mutate_ncp_cipher_list("vollbit", &gc), NULL);
80  assert_ptr_equal(mutate_ncp_cipher_list("AES-256-GCM:vollbit", &gc), NULL);
82 
84  "ChaCha20-Poly1305:ChaCha20-Poly1305:ChaCha20-Poly1305:"
85  "ChaCha20-Poly1305:ChaCha20-Poly1305:ChaCha20-Poly1305:"
86  "ChaCha20-Poly1305", &gc), NULL);
87 
88 #ifdef ENABLE_CRYPTO_OPENSSL
89  assert_string_equal(mutate_ncp_cipher_list("id-aes128-GCM:id-aes256-GCM",
90  &gc), "AES-128-GCM:AES-256-GCM");
91 #else
93  &gc), "BF-CBC");
94 #endif
95  gc_free(&gc);
96 }
97 
98 static void
100 {
101  struct gc_arena gc = gc_new();
102  const char *client_peer_info;
103  const char *peer_list;
104 
105  client_peer_info = "foo=bar\nIV_foo=y\nIV_NCP=2";
106  peer_list = tls_peer_ncp_list(client_peer_info, &gc);
107  assert_string_equal(aes_ciphers,peer_list);
108  assert_true(tls_peer_supports_ncp(client_peer_info));
109 
110  client_peer_info = "foo=bar\nIV_foo=y\nIV_NCP=2\nIV_CIPHERS=BF-CBC";
111  peer_list = tls_peer_ncp_list(client_peer_info, &gc);
112  assert_string_equal("BF-CBC", peer_list);
113  assert_true(tls_peer_supports_ncp(client_peer_info));
114 
115  client_peer_info = "IV_NCP=2\nIV_CIPHERS=BF-CBC:FOO-BAR\nIV_BAR=7";
116  peer_list = tls_peer_ncp_list(client_peer_info, &gc);
117  assert_string_equal("BF-CBC:FOO-BAR", peer_list);
118  assert_true(tls_peer_supports_ncp(client_peer_info));
119 
120  client_peer_info = "IV_CIPHERS=BF-CBC:FOO-BAR\nIV_BAR=7";
121  peer_list = tls_peer_ncp_list(client_peer_info, &gc);
122  assert_string_equal("BF-CBC:FOO-BAR", peer_list);
123  assert_true(tls_peer_supports_ncp(client_peer_info));
124 
125  client_peer_info = "IV_YOLO=NO\nIV_BAR=7";
126  peer_list = tls_peer_ncp_list(client_peer_info, &gc);
127  assert_string_equal("", peer_list);
128  assert_false(tls_peer_supports_ncp(client_peer_info));
129 
130  peer_list = tls_peer_ncp_list(NULL, &gc);
131  assert_string_equal("", peer_list);
132  assert_false(tls_peer_supports_ncp(client_peer_info));
133 
134  gc_free(&gc);
135 }
136 
137 static void
138 test_poor_man(void **state)
139 {
140  struct gc_arena gc = gc_new();
141  char *best_cipher;
142 
143  const char *serverlist = "CHACHA20_POLY1305:AES-128-GCM";
144  const char *serverlistbfcbc = "CHACHA20_POLY1305:AES-128-GCM:BF-CBC:none";
145 
146  best_cipher = ncp_get_best_cipher(serverlist,
147  "IV_YOLO=NO\nIV_BAR=7",
148  "BF-CBC", &gc);
149 
150  assert_ptr_equal(best_cipher, NULL);
151 
152 
153  best_cipher = ncp_get_best_cipher(serverlistbfcbc,
154  "IV_YOLO=NO\nIV_BAR=7",
155  "BF-CBC", &gc);
156 
157  assert_string_equal(best_cipher, "BF-CBC");
158 
159 
160  best_cipher = ncp_get_best_cipher(serverlist,
161  "IV_NCP=1\nIV_BAR=7",
162  "AES-128-GCM", &gc);
163 
164  assert_string_equal(best_cipher, "AES-128-GCM");
165 
166  best_cipher = ncp_get_best_cipher(serverlist, NULL,
167  "AES-128-GCM", &gc);
168 
169  assert_string_equal(best_cipher, "AES-128-GCM");
170 
171  best_cipher = ncp_get_best_cipher(serverlist, NULL,
172  "none", &gc);
173  assert_ptr_equal(best_cipher, NULL);
174 
175  best_cipher = ncp_get_best_cipher(serverlistbfcbc, NULL,
176  "none", &gc);
177  assert_string_equal(best_cipher, "none");
178 
179  best_cipher = ncp_get_best_cipher(serverlist, NULL,NULL, &gc);
180  assert_ptr_equal(best_cipher, NULL);
181 
182  gc_free(&gc);
183 }
184 
185 
186 static void
187 test_ncp_best(void **state)
188 {
189  struct gc_arena gc = gc_new();
190  char *best_cipher;
191 
192  const char *serverlist = "CHACHA20_POLY1305:AES-128-GCM:AES-256-GCM";
193 
194  best_cipher = ncp_get_best_cipher(serverlist,
195  "IV_YOLO=NO\nIV_NCP=2\nIV_BAR=7",
196  "BF-CBC", &gc);
197 
198  assert_string_equal(best_cipher, "AES-128-GCM");
199 
200  /* Best cipher is in --cipher of client */
201  best_cipher = ncp_get_best_cipher(serverlist, "IV_NCP=2\nIV_BAR=7",
202  "CHACHA20_POLY1305", &gc);
203 
204  assert_string_equal(best_cipher, "CHACHA20_POLY1305");
205 
206  /* Best cipher is in --cipher of client */
207  best_cipher = ncp_get_best_cipher(serverlist, "IV_CIPHERS=AES-128-GCM",
208  "AES-256-CBC", &gc);
209 
210 
211  assert_string_equal(best_cipher, "AES-128-GCM");
212 
213  /* IV_NCP=2 should be ignored if IV_CIPHERS is sent */
214  best_cipher = ncp_get_best_cipher(serverlist,
215  "IV_FOO=7\nIV_CIPHERS=AES-256-GCM\nIV_NCP=2",
216  "AES-256-CBC", &gc);
217 
218  assert_string_equal(best_cipher, "AES-256-GCM");
219 
220 
221  gc_free(&gc);
222 }
223 
224 
225 
226 const struct CMUnitTest ncp_tests[] = {
231 };
232 
233 
234 int
235 main(void)
236 {
237 #if defined(ENABLE_CRYPTO_OPENSSL)
238  OpenSSL_add_all_algorithms();
239 #endif
240  return cmocka_run_group_tests(ncp_tests, NULL, NULL);
241 }
#define assert_true(c)
Definition: cmocka.h:1045
#define cmocka_unit_test(f)
Initializes a CMUnitTest structure.
Definition: cmocka.h:1653
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1023
#define assert_ptr_equal(a, b)
Definition: cmocka.h:1136
const char * aes_ciphers
Definition: test_ncp.c:45
bool tls_peer_supports_ncp(const char *peer_info)
Returns whether the client supports NCP either by announcing IV_NCP>=2 or the IV_CIPHERS list...
Definition: ssl_ncp.c:78
#define assert_string_equal(a, b)
Definition: cmocka.h:1214
static struct gc_arena gc_new(void)
Definition: buffer.h:1015
int main(void)
Definition: test_ncp.c:235
char * ncp_get_best_cipher(const char *server_list, const char *peer_info, const char *remote_cipher, struct gc_arena *gc)
Iterates through the ciphers in server_list and return the first cipher that is also supported by the...
Definition: ssl_ncp.c:229
static void test_poor_man(void **state)
Definition: test_ncp.c:138
const struct CMUnitTest ncp_tests[]
Definition: test_ncp.c:226
const char * tls_peer_ncp_list(const char *peer_info, struct gc_arena *gc)
Returns the support cipher list from the peer according to the IV_NCP and IV_CIPHER values in peer_in...
Definition: ssl_ncp.c:195
#define cmocka_run_group_tests(group_tests, group_setup, group_teardown)
Definition: cmocka.h:1749
static void test_extract_client_ciphers(void **state)
Definition: test_ncp.c:99
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
const char * bf_chacha
Definition: test_ncp.c:44
static void test_check_ncp_ciphers_list(void **state)
Definition: test_ncp.c:48
static void test_ncp_best(void **state)
Definition: test_ncp.c:187
char * mutate_ncp_cipher_list(const char *list, struct gc_arena *gc)
Check whether the ciphers in the supplied list are supported.
Definition: ssl_ncp.c:96
#define assert_false(c)
Definition: cmocka.h:1063
const cipher_kt_t * cipher_kt_get(const char *ciphername)
Return cipher parameters, based on the given cipher name.