]> git.ipfire.org Git - thirdparty/openvpn.git/blob - tests/unit_tests/openvpn/test_crypto.c
Remove all traces of the previous MSVC build system
[thirdparty/openvpn.git] / tests / unit_tests / openvpn / test_crypto.c
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) 2016-2021 Fox Crypto B.V. <openvpn@foxcrypto.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27
28 #include "syshead.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <setjmp.h>
35 #include <cmocka.h>
36
37 #include "crypto.h"
38 #include "options.h"
39 #include "ssl_backend.h"
40
41 #include "mock_msg.h"
42 #include "mss.h"
43
44 static const char testtext[] = "Dummy text to test PEM encoding";
45
46 static void
47 crypto_pem_encode_decode_loopback(void **state)
48 {
49 struct gc_arena gc = gc_new();
50 struct buffer src_buf;
51 buf_set_read(&src_buf, (void *)testtext, sizeof(testtext));
52
53 uint8_t dec[sizeof(testtext)];
54 struct buffer dec_buf;
55 buf_set_write(&dec_buf, dec, sizeof(dec));
56
57 struct buffer pem_buf;
58
59 assert_true(crypto_pem_encode("TESTKEYNAME", &pem_buf, &src_buf, &gc));
60 assert_true(BLEN(&src_buf) < BLEN(&pem_buf));
61
62 /* Wrong key name */
63 assert_false(crypto_pem_decode("WRONGNAME", &dec_buf, &pem_buf));
64
65 assert_true(crypto_pem_decode("TESTKEYNAME", &dec_buf, &pem_buf));
66 assert_int_equal(BLEN(&src_buf), BLEN(&dec_buf));
67 assert_memory_equal(BPTR(&src_buf), BPTR(&dec_buf), BLEN(&src_buf));
68
69 gc_free(&gc);
70 }
71
72 static void
73 test_translate_cipher(const char *ciphername, const char *openvpn_name)
74 {
75 bool cipher = cipher_valid(ciphername);
76
77 /* Empty cipher is fine */
78 if (!cipher)
79 {
80 return;
81 }
82
83 const char *kt_name = cipher_kt_name(ciphername);
84
85 assert_string_equal(kt_name, openvpn_name);
86 }
87
88 static void
89 test_cipher_names(const char *ciphername, const char *openvpn_name)
90 {
91 struct gc_arena gc = gc_new();
92 /* Go through some variants, if the cipher library accepts these, they
93 * should be normalised to the openvpn name */
94 char *upper = string_alloc(ciphername, &gc);
95 char *lower = string_alloc(ciphername, &gc);
96 char *random_case = string_alloc(ciphername, &gc);
97
98 for (int i = 0; i < strlen(ciphername); i++)
99 {
100 upper[i] = toupper(ciphername[i]);
101 lower[i] = tolower(ciphername[i]);
102 if (rand() & 0x1)
103 {
104 random_case[i] = upper[i];
105 }
106 else
107 {
108 random_case[i] = lower[i];
109 }
110 }
111
112 if (!openvpn_name)
113 {
114 openvpn_name = upper;
115 }
116
117 test_translate_cipher(upper, openvpn_name);
118 test_translate_cipher(lower, openvpn_name);
119 test_translate_cipher(random_case, openvpn_name);
120 test_translate_cipher(ciphername, openvpn_name);
121
122
123 gc_free(&gc);
124 }
125
126 static void
127 crypto_translate_cipher_names(void **state)
128 {
129 /* Test that a number of ciphers to see that they turn out correctly */
130 test_cipher_names("BF-CBC", NULL);
131 test_cipher_names("BLOWFISH-CBC", "BF-CBC");
132 test_cipher_names("Chacha20-Poly1305", NULL);
133 test_cipher_names("AES-128-GCM", NULL);
134 test_cipher_names("AES-128-CBC", NULL);
135 test_cipher_names("CAMELLIA-128-CFB128", "CAMELLIA-128-CFB");
136 test_cipher_names("id-aes256-GCM", "AES-256-GCM");
137 }
138
139
140 static uint8_t good_prf[32] = {0xd9, 0x8c, 0x85, 0x18, 0xc8, 0x5e, 0x94, 0x69,
141 0x27, 0x91, 0x6a, 0xcf, 0xc2, 0xd5, 0x92, 0xfb,
142 0xb1, 0x56, 0x7e, 0x4b, 0x4b, 0x14, 0x59, 0xe6,
143 0xa9, 0x04, 0xac, 0x2d, 0xda, 0xb7, 0x2d, 0x67};
144
145 static const char *ipsumlorem = "Lorem ipsum dolor sit amet, consectetur "
146 "adipisici elit, sed eiusmod tempor incidunt "
147 "ut labore et dolore magna aliqua.";
148
149 static void
150 crypto_test_tls_prf(void **state)
151 {
152 const char *seedstr = "Quis aute iure reprehenderit in voluptate "
153 "velit esse cillum dolore";
154 const unsigned char *seed = (const unsigned char *)seedstr;
155 const size_t seed_len = strlen(seedstr);
156
157
158 const unsigned char *secret = (const unsigned char *) ipsumlorem;
159 size_t secret_len = strlen((const char *)secret);
160
161
162 uint8_t out[32];
163 ssl_tls1_PRF(seed, seed_len, secret, secret_len, out, sizeof(out));
164
165 assert_memory_equal(good_prf, out, sizeof(out));
166 }
167
168 static uint8_t testkey[20] = {0x0b, 0x00};
169 static uint8_t goodhash[20] = {0x58, 0xea, 0x5a, 0xf0, 0x42, 0x94, 0xe9, 0x17,
170 0xed, 0x84, 0xb9, 0xf0, 0x83, 0x30, 0x23, 0xae,
171 0x8b, 0xa7, 0x7e, 0xb8};
172
173 static void
174 crypto_test_hmac(void **state)
175 {
176 hmac_ctx_t *hmac = hmac_ctx_new();
177
178 assert_int_equal(md_kt_size("SHA1"), 20);
179
180 uint8_t key[20];
181 memcpy(key, testkey, sizeof(key));
182
183 hmac_ctx_init(hmac, key, "SHA1");
184 hmac_ctx_update(hmac, (const uint8_t *)ipsumlorem, (int) strlen(ipsumlorem));
185 hmac_ctx_update(hmac, (const uint8_t *)ipsumlorem, (int) strlen(ipsumlorem));
186
187 uint8_t hash[20];
188 hmac_ctx_final(hmac, hash);
189
190 assert_memory_equal(hash, goodhash, sizeof(hash));
191 memset(hash, 0x00, sizeof(hash));
192
193 /* try again */
194 hmac_ctx_reset(hmac);
195 hmac_ctx_update(hmac, (const uint8_t *)ipsumlorem, (int) strlen(ipsumlorem));
196 hmac_ctx_update(hmac, (const uint8_t *)ipsumlorem, (int) strlen(ipsumlorem));
197 hmac_ctx_final(hmac, hash);
198
199 assert_memory_equal(hash, goodhash, sizeof(hash));
200
201 /* Fill our key with random data to ensure it is not used by hmac anymore */
202 memset(key, 0x55, sizeof(key));
203
204 hmac_ctx_reset(hmac);
205 hmac_ctx_update(hmac, (const uint8_t *)ipsumlorem, (int) strlen(ipsumlorem));
206 hmac_ctx_update(hmac, (const uint8_t *)ipsumlorem, (int) strlen(ipsumlorem));
207 hmac_ctx_final(hmac, hash);
208
209 assert_memory_equal(hash, goodhash, sizeof(hash));
210 hmac_ctx_cleanup(hmac);
211 hmac_ctx_free(hmac);
212 }
213
214 void
215 test_des_encrypt(void **state)
216 {
217 /* We have a small des encrypt method that is only for NTLMv1. This unit
218 * test ensures that it is not accidentally broken */
219
220 const unsigned char des_key[DES_KEY_LENGTH] = {0x42, 0x23};
221
222 const char *src = "MoinWelt";
223
224 /* cipher_des_encrypt_ecb wants a non const */
225 unsigned char *src2 = (unsigned char *) strdup(src);
226
227 unsigned char dst[DES_KEY_LENGTH];
228 cipher_des_encrypt_ecb(des_key, src2, dst);
229
230 const unsigned char dst_good[DES_KEY_LENGTH] = {0xd3, 0x8f, 0x61, 0xf7, 0xbe, 0x27, 0xb6, 0xa2};
231
232 assert_memory_equal(dst, dst_good, DES_KEY_LENGTH);
233
234 free(src2);
235 }
236
237 /* This test is in test_crypto as it calls into the functions that calculate
238 * the crypto overhead */
239 static void
240 test_occ_mtu_calculation(void **state)
241 {
242 struct gc_arena gc = gc_new();
243
244 struct frame f = { 0 };
245 struct options o = { 0 };
246 size_t linkmtu;
247
248 /* common defaults */
249 o.ce.tun_mtu = 1400;
250 o.replay = true;
251 o.ce.proto = PROTO_UDP;
252
253 /* No crypto at all */
254 o.ciphername = "none";
255 o.authname = "none";
256 linkmtu = calc_options_string_link_mtu(&o, &f);
257 assert_int_equal(linkmtu, 1400);
258
259 /* Static key OCC examples */
260 o.shared_secret_file = "not null";
261
262 /* secret, auth none, cipher none */
263 o.ciphername = "none";
264 o.authname = "none";
265 linkmtu = calc_options_string_link_mtu(&o, &f);
266 assert_int_equal(linkmtu, 1408);
267
268 /* secret, cipher AES-128-CBC, auth none */
269 o.ciphername = "AES-128-CBC";
270 o.authname = "none";
271 linkmtu = calc_options_string_link_mtu(&o, &f);
272 assert_int_equal(linkmtu, 1440);
273
274 /* secret, cipher none, auth SHA256 */
275 o.ciphername = "none";
276 o.authname = "SHA256";
277 linkmtu = calc_options_string_link_mtu(&o, &f);
278 assert_int_equal(linkmtu, 1440);
279
280 /* secret, cipher BF-CBC, auth SHA1 */
281 o.ciphername = "BF-CBC";
282 o.authname = "SHA1";
283 linkmtu = calc_options_string_link_mtu(&o, &f);
284 assert_int_equal(linkmtu, 1444);
285
286 /* secret, cipher BF-CBC, auth SHA1, tcp-client */
287 o.ce.proto = PROTO_TCP_CLIENT;
288 linkmtu = calc_options_string_link_mtu(&o, &f);
289 assert_int_equal(linkmtu, 1446);
290
291 o.ce.proto = PROTO_UDP;
292
293 #if defined(USE_COMP)
294 o.comp.alg = COMP_ALG_LZO;
295
296 /* secret, comp-lzo yes, cipher BF-CBC, auth SHA1 */
297 linkmtu = calc_options_string_link_mtu(&o, &f);
298 assert_int_equal(linkmtu, 1445);
299
300 #if defined(ENABLE_FRAGMENT)
301 /* secret, comp-lzo yes, cipher BF-CBC, auth SHA1, fragment 1200 */
302 o.ce.fragment = 1200;
303 linkmtu = calc_options_string_link_mtu(&o, &f);
304 assert_int_equal(linkmtu, 1449);
305 o.ce.fragment = 0;
306 #endif
307
308 o.comp.alg = COMP_ALG_UNDEF;
309 #endif
310
311 /* TLS mode */
312 o.shared_secret_file = NULL;
313 o.tls_client = true;
314 o.pull = true;
315
316 /* tls client, cipher AES-128-CBC, auth SHA1, tls-auth */
317 o.authname = "SHA1";
318 o.ciphername = "AES-128-CBC";
319 o.tls_auth_file = "dummy";
320
321 linkmtu = calc_options_string_link_mtu(&o, &f);
322 assert_int_equal(linkmtu, 1457);
323
324 /* tls client, cipher AES-128-CBC, auth SHA1 */
325 o.tls_auth_file = NULL;
326
327 linkmtu = calc_options_string_link_mtu(&o, &f);
328 assert_int_equal(linkmtu, 1457);
329
330 /* tls client, cipher none, auth none */
331 o.authname = "none";
332 o.ciphername = "none";
333
334 linkmtu = calc_options_string_link_mtu(&o, &f);
335 assert_int_equal(linkmtu, 1405);
336
337 /* tls client, auth none, cipher none, no-replay */
338 o.replay = false;
339
340 linkmtu = calc_options_string_link_mtu(&o, &f);
341 assert_int_equal(linkmtu, 1401);
342
343
344 o.replay = true;
345
346 /* tls client, auth SHA1, cipher AES-256-GCM */
347 o.authname = "SHA1";
348 o.ciphername = "AES-256-GCM";
349 linkmtu = calc_options_string_link_mtu(&o, &f);
350 assert_int_equal(linkmtu, 1449);
351
352
353 #if defined(USE_COMP) && defined(ENABLE_FRAGMENT)
354 o.comp.alg = COMP_ALG_LZO;
355
356 /* tls client, auth SHA1, cipher AES-256-GCM, fragment, comp-lzo yes */
357 o.ce.fragment = 1200;
358 linkmtu = calc_options_string_link_mtu(&o, &f);
359 assert_int_equal(linkmtu, 1454);
360
361 /* tls client, auth SHA1, cipher AES-256-GCM, fragment, comp-lzo yes, socks */
362 o.ce.socks_proxy_server = "socks.example.com";
363 linkmtu = calc_options_string_link_mtu(&o, &f);
364 assert_int_equal(linkmtu, 1464);
365 #endif
366
367 gc_free(&gc);
368 }
369
370 static void
371 test_mssfix_mtu_calculation(void **state)
372 {
373 struct gc_arena gc = gc_new();
374
375 struct frame f = { 0 };
376 struct options o = { 0 };
377
378 /* common defaults */
379 o.ce.tun_mtu = 1400;
380 o.ce.mssfix = 1000;
381 o.replay = true;
382 o.ce.proto = PROTO_UDP;
383
384 /* No crypto at all */
385 o.ciphername = "none";
386 o.authname = "none";
387 struct key_type kt;
388 init_key_type(&kt, o.ciphername, o.authname, false, false);
389
390 /* No encryption, just packet id (8) + TCP payload(20) + IP payload(20) */
391 frame_calculate_dynamic(&f, &kt, &o, NULL);
392 assert_int_equal(f.mss_fix, 952);
393
394 /* Static key OCC examples */
395 o.shared_secret_file = "not null";
396
397 /* secret, auth none, cipher none */
398 o.ciphername = "none";
399 o.authname = "none";
400 init_key_type(&kt, o.ciphername, o.authname, false, false);
401 frame_calculate_dynamic(&f, &kt, &o, NULL);
402 assert_int_equal(f.mss_fix, 952);
403
404 /* secret, cipher AES-128-CBC, auth none */
405 o.ciphername = "AES-128-CBC";
406 o.authname = "none";
407 init_key_type(&kt, o.ciphername, o.authname, false, false);
408
409 for (int i = 990; i <= 1010; i++)
410 {
411 /* 992 - 1008 should end up with the same mssfix value all they
412 * all result in the same CBC block size/padding and <= 991 and >=1008
413 * should be one block less and more respectively */
414 o.ce.mssfix = i;
415 frame_calculate_dynamic(&f, &kt, &o, NULL);
416 if (i <= 991)
417 {
418 assert_int_equal(f.mss_fix, 911);
419 }
420 else if (i >= 1008)
421 {
422 assert_int_equal(f.mss_fix, 943);
423 }
424 else
425 {
426 assert_int_equal(f.mss_fix, 927);
427 }
428 }
429 #ifdef USE_COMP
430 o.comp.alg = COMP_ALG_LZO;
431
432 /* Same but with compression added. Compression adds one byte extra to the
433 * payload so the payload should be reduced by compared to the no
434 * compression calculation before */
435 for (int i = 990; i <= 1010; i++)
436 {
437 /* 992 - 1008 should end up with the same mssfix value all they
438 * all result in the same CBC block size/padding and <= 991 and >=1008
439 * should be one block less and more respectively */
440 o.ce.mssfix = i;
441 frame_calculate_dynamic(&f, &kt, &o, NULL);
442 if (i <= 991)
443 {
444 assert_int_equal(f.mss_fix, 910);
445 }
446 else if (i >= 1008)
447 {
448 assert_int_equal(f.mss_fix, 942);
449 }
450 else
451 {
452 assert_int_equal(f.mss_fix, 926);
453 }
454 }
455 o.comp.alg = COMP_ALG_UNDEF;
456 #endif /* ifdef USE_COMP */
457
458 /* tls client, auth SHA1, cipher AES-256-GCM */
459 o.authname = "SHA1";
460 o.ciphername = "AES-256-GCM";
461 o.tls_client = true;
462 o.peer_id = 77;
463 o.use_peer_id = true;
464 init_key_type(&kt, o.ciphername, o.authname, true, false);
465
466 for (int i = 900; i <= 1200; i++)
467 {
468 /* For stream ciphers, the value should not be influenced by block
469 * sizes or similar but always have the same difference */
470 o.ce.mssfix = i;
471 frame_calculate_dynamic(&f, &kt, &o, NULL);
472
473 /* 4 byte opcode/peerid, 4 byte pkt ID, 16 byte tag, 40 TCP+IP */
474 assert_int_equal(f.mss_fix, i - 4 - 4 - 16 - 40);
475 }
476
477 gc_free(&gc);
478 }
479
480 int
481 main(void)
482 {
483 const struct CMUnitTest tests[] = {
484 cmocka_unit_test(crypto_pem_encode_decode_loopback),
485 cmocka_unit_test(crypto_translate_cipher_names),
486 cmocka_unit_test(crypto_test_tls_prf),
487 cmocka_unit_test(crypto_test_hmac),
488 cmocka_unit_test(test_des_encrypt),
489 cmocka_unit_test(test_occ_mtu_calculation),
490 cmocka_unit_test(test_mssfix_mtu_calculation)
491 };
492
493 #if defined(ENABLE_CRYPTO_OPENSSL)
494 OpenSSL_add_all_algorithms();
495 #endif
496
497 int ret = cmocka_run_group_tests_name("crypto tests", tests, NULL, NULL);
498
499 #if defined(ENABLE_CRYPTO_OPENSSL)
500 EVP_cleanup();
501 #endif
502
503 return ret;
504 }