1 /*
2 * Copyright (C) 2015 Red Hat, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
17 *
18 * Author: Daniel P. Berrange <berrange@redhat.com>
19 */
20
21 #include "qemu/osdep.h"
22
23 #include "crypto-tls-x509-helpers.h"
24 #include "crypto-tls-psk-helpers.h"
25 #include "crypto/tlscredsx509.h"
26 #include "crypto/tlscredspsk.h"
27 #include "crypto/tlssession.h"
28 #include "qom/object_interfaces.h"
29 #include "qapi/error.h"
30 #include "qemu/module.h"
31 #include "qemu/sockets.h"
32 #include "authz/list.h"
33
34 #define WORKDIR "tests/test-crypto-tlssession-work/"
35 #define PSKFILE WORKDIR "keys.psk"
36 #define KEYFILE WORKDIR "key-ctx.pem"
37
38 static ssize_t
testWrite(const char * buf,size_t len,void * opaque,Error ** errp)39 testWrite(const char *buf, size_t len, void *opaque, Error **errp)
40 {
41 int *fd = opaque;
42 int ret;
43
44 ret = write(*fd, buf, len);
45 if (ret < 0) {
46 if (errno == EAGAIN) {
47 return QCRYPTO_TLS_SESSION_ERR_BLOCK;
48 } else {
49 error_setg_errno(errp, errno, "unable to write");
50 return -1;
51 }
52 }
53 return ret;
54 }
55
56 static ssize_t
testRead(char * buf,size_t len,void * opaque,Error ** errp)57 testRead(char *buf, size_t len, void *opaque, Error **errp)
58 {
59 int *fd = opaque;
60 int ret;
61
62 ret = read(*fd, buf, len);
63 if (ret < 0) {
64 if (errno == EAGAIN) {
65 return QCRYPTO_TLS_SESSION_ERR_BLOCK;
66 } else {
67 error_setg_errno(errp, errno, "unable to read");
68 return -1;
69 }
70 }
71 return ret;
72 }
73
test_tls_creds_psk_create(QCryptoTLSCredsEndpoint endpoint,const char * dir)74 static QCryptoTLSCreds *test_tls_creds_psk_create(
75 QCryptoTLSCredsEndpoint endpoint,
76 const char *dir)
77 {
78 Object *parent = object_get_objects_root();
79 Object *creds = object_new_with_props(
80 TYPE_QCRYPTO_TLS_CREDS_PSK,
81 parent,
82 (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
83 "testtlscredsserver" : "testtlscredsclient"),
84 &error_abort,
85 "endpoint", (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
86 "server" : "client"),
87 "dir", dir,
88 "priority", "NORMAL",
89 NULL
90 );
91 return QCRYPTO_TLS_CREDS(creds);
92 }
93
94
test_crypto_tls_session_psk(void)95 static void test_crypto_tls_session_psk(void)
96 {
97 QCryptoTLSCreds *clientCreds;
98 QCryptoTLSCreds *serverCreds;
99 QCryptoTLSSession *clientSess = NULL;
100 QCryptoTLSSession *serverSess = NULL;
101 int channel[2];
102 bool clientShake = false;
103 bool serverShake = false;
104 int ret;
105
106 /* We'll use this for our fake client-server connection */
107 ret = qemu_socketpair(AF_UNIX, SOCK_STREAM, 0, channel);
108 g_assert(ret == 0);
109
110 /*
111 * We have an evil loop to do the handshake in a single
112 * thread, so we need these non-blocking to avoid deadlock
113 * of ourselves
114 */
115 qemu_socket_set_nonblock(channel[0]);
116 qemu_socket_set_nonblock(channel[1]);
117
118 clientCreds = test_tls_creds_psk_create(
119 QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
120 WORKDIR);
121 g_assert(clientCreds != NULL);
122
123 serverCreds = test_tls_creds_psk_create(
124 QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
125 WORKDIR);
126 g_assert(serverCreds != NULL);
127
128 /* Now the real part of the test, setup the sessions */
129 clientSess = qcrypto_tls_session_new(
130 clientCreds, NULL, NULL,
131 QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, &error_abort);
132 g_assert(clientSess != NULL);
133
134 serverSess = qcrypto_tls_session_new(
135 serverCreds, NULL, NULL,
136 QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, &error_abort);
137 g_assert(serverSess != NULL);
138
139 /* For handshake to work, we need to set the I/O callbacks
140 * to read/write over the socketpair
141 */
142 qcrypto_tls_session_set_callbacks(serverSess,
143 testWrite, testRead,
144 &channel[0]);
145 qcrypto_tls_session_set_callbacks(clientSess,
146 testWrite, testRead,
147 &channel[1]);
148
149 /*
150 * Finally we loop around & around doing handshake on each
151 * session until we get an error, or the handshake completes.
152 * This relies on the socketpair being nonblocking to avoid
153 * deadlocking ourselves upon handshake
154 */
155 do {
156 int rv;
157 if (!serverShake) {
158 rv = qcrypto_tls_session_handshake(serverSess,
159 &error_abort);
160 g_assert(rv >= 0);
161 if (qcrypto_tls_session_get_handshake_status(serverSess) ==
162 QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
163 serverShake = true;
164 }
165 }
166 if (!clientShake) {
167 rv = qcrypto_tls_session_handshake(clientSess,
168 &error_abort);
169 g_assert(rv >= 0);
170 if (qcrypto_tls_session_get_handshake_status(clientSess) ==
171 QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
172 clientShake = true;
173 }
174 }
175 } while (!clientShake || !serverShake);
176
177
178 /* Finally make sure the server & client validation is successful. */
179 g_assert(qcrypto_tls_session_check_credentials(serverSess,
180 &error_abort) == 0);
181 g_assert(qcrypto_tls_session_check_credentials(clientSess,
182 &error_abort) == 0);
183
184 object_unparent(OBJECT(serverCreds));
185 object_unparent(OBJECT(clientCreds));
186
187 qcrypto_tls_session_free(serverSess);
188 qcrypto_tls_session_free(clientSess);
189
190 close(channel[0]);
191 close(channel[1]);
192 }
193
194
195 struct QCryptoTLSSessionTestData {
196 const char *servercacrt;
197 const char *clientcacrt;
198 const char *servercrt;
199 const char *clientcrt;
200 bool expectServerFail;
201 bool expectClientFail;
202 const char *hostname;
203 const char *const *wildcards;
204 };
205
test_tls_creds_x509_create(QCryptoTLSCredsEndpoint endpoint,const char * certdir)206 static QCryptoTLSCreds *test_tls_creds_x509_create(
207 QCryptoTLSCredsEndpoint endpoint,
208 const char *certdir)
209 {
210 Object *parent = object_get_objects_root();
211 Object *creds = object_new_with_props(
212 TYPE_QCRYPTO_TLS_CREDS_X509,
213 parent,
214 (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
215 "testtlscredsserver" : "testtlscredsclient"),
216 &error_abort,
217 "endpoint", (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER ?
218 "server" : "client"),
219 "dir", certdir,
220 "verify-peer", "yes",
221 "priority", "NORMAL",
222 /* We skip initial sanity checks here because we
223 * want to make sure that problems are being
224 * detected at the TLS session validation stage,
225 * and the test-crypto-tlscreds test already
226 * validate the sanity check code.
227 */
228 "sanity-check", "no",
229 NULL
230 );
231 return QCRYPTO_TLS_CREDS(creds);
232 }
233
234
235 /*
236 * This tests validation checking of peer certificates
237 *
238 * This is replicating the checks that are done for an
239 * active TLS session after handshake completes. To
240 * simulate that we create our TLS contexts, skipping
241 * sanity checks. We then get a socketpair, and
242 * initiate a TLS session across them. Finally do
243 * do actual cert validation tests
244 */
test_crypto_tls_session_x509(const void * opaque)245 static void test_crypto_tls_session_x509(const void *opaque)
246 {
247 struct QCryptoTLSSessionTestData *data =
248 (struct QCryptoTLSSessionTestData *)opaque;
249 QCryptoTLSCreds *clientCreds;
250 QCryptoTLSCreds *serverCreds;
251 QCryptoTLSSession *clientSess = NULL;
252 QCryptoTLSSession *serverSess = NULL;
253 QAuthZList *auth;
254 const char * const *wildcards;
255 int channel[2];
256 bool clientShake = false;
257 bool serverShake = false;
258 int ret;
259
260 /* We'll use this for our fake client-server connection */
261 ret = qemu_socketpair(AF_UNIX, SOCK_STREAM, 0, channel);
262 g_assert(ret == 0);
263
264 /*
265 * We have an evil loop to do the handshake in a single
266 * thread, so we need these non-blocking to avoid deadlock
267 * of ourselves
268 */
269 qemu_socket_set_nonblock(channel[0]);
270 qemu_socket_set_nonblock(channel[1]);
271
272 #define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/"
273 #define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/"
274 g_mkdir_with_parents(CLIENT_CERT_DIR, 0700);
275 g_mkdir_with_parents(SERVER_CERT_DIR, 0700);
276
277 unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
278 unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
279 unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
280
281 unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
282 unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
283 unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
284
285 g_assert(link(data->servercacrt,
286 SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0);
287 g_assert(link(data->servercrt,
288 SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT) == 0);
289 g_assert(link(KEYFILE,
290 SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY) == 0);
291
292 g_assert(link(data->clientcacrt,
293 CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0);
294 g_assert(link(data->clientcrt,
295 CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT) == 0);
296 g_assert(link(KEYFILE,
297 CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY) == 0);
298
299 clientCreds = test_tls_creds_x509_create(
300 QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
301 CLIENT_CERT_DIR);
302 g_assert(clientCreds != NULL);
303
304 serverCreds = test_tls_creds_x509_create(
305 QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
306 SERVER_CERT_DIR);
307 g_assert(serverCreds != NULL);
308
309 auth = qauthz_list_new("tlssessionacl",
310 QAUTHZ_LIST_POLICY_DENY,
311 &error_abort);
312 wildcards = data->wildcards;
313 while (wildcards && *wildcards) {
314 qauthz_list_append_rule(auth, *wildcards,
315 QAUTHZ_LIST_POLICY_ALLOW,
316 QAUTHZ_LIST_FORMAT_GLOB,
317 &error_abort);
318 wildcards++;
319 }
320
321 /* Now the real part of the test, setup the sessions */
322 clientSess = qcrypto_tls_session_new(
323 clientCreds, data->hostname, NULL,
324 QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, &error_abort);
325 g_assert(clientSess != NULL);
326
327 serverSess = qcrypto_tls_session_new(
328 serverCreds, NULL,
329 data->wildcards ? "tlssessionacl" : NULL,
330 QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, &error_abort);
331 g_assert(serverSess != NULL);
332
333 /* For handshake to work, we need to set the I/O callbacks
334 * to read/write over the socketpair
335 */
336 qcrypto_tls_session_set_callbacks(serverSess,
337 testWrite, testRead,
338 &channel[0]);
339 qcrypto_tls_session_set_callbacks(clientSess,
340 testWrite, testRead,
341 &channel[1]);
342
343 /*
344 * Finally we loop around & around doing handshake on each
345 * session until we get an error, or the handshake completes.
346 * This relies on the socketpair being nonblocking to avoid
347 * deadlocking ourselves upon handshake
348 */
349 do {
350 int rv;
351 if (!serverShake) {
352 rv = qcrypto_tls_session_handshake(serverSess,
353 &error_abort);
354 g_assert(rv >= 0);
355 if (qcrypto_tls_session_get_handshake_status(serverSess) ==
356 QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
357 serverShake = true;
358 }
359 }
360 if (!clientShake) {
361 rv = qcrypto_tls_session_handshake(clientSess,
362 &error_abort);
363 g_assert(rv >= 0);
364 if (qcrypto_tls_session_get_handshake_status(clientSess) ==
365 QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
366 clientShake = true;
367 }
368 }
369 } while (!clientShake || !serverShake);
370
371
372 /* Finally make sure the server validation does what
373 * we were expecting
374 */
375 if (qcrypto_tls_session_check_credentials(
376 serverSess, data->expectServerFail ? NULL : &error_abort) < 0) {
377 g_assert(data->expectServerFail);
378 } else {
379 g_assert(!data->expectServerFail);
380 }
381
382 /*
383 * And the same for the client validation check
384 */
385 if (qcrypto_tls_session_check_credentials(
386 clientSess, data->expectClientFail ? NULL : &error_abort) < 0) {
387 g_assert(data->expectClientFail);
388 } else {
389 g_assert(!data->expectClientFail);
390 }
391
392 unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
393 unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT);
394 unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY);
395
396 unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT);
397 unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT);
398 unlink(CLIENT_CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY);
399
400 rmdir(CLIENT_CERT_DIR);
401 rmdir(SERVER_CERT_DIR);
402
403 object_unparent(OBJECT(serverCreds));
404 object_unparent(OBJECT(clientCreds));
405 object_unparent(OBJECT(auth));
406
407 qcrypto_tls_session_free(serverSess);
408 qcrypto_tls_session_free(clientSess);
409
410 close(channel[0]);
411 close(channel[1]);
412 }
413
414
main(int argc,char ** argv)415 int main(int argc, char **argv)
416 {
417 int ret;
418
419 module_call_init(MODULE_INIT_QOM);
420 g_test_init(&argc, &argv, NULL);
421 g_setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1);
422
423 g_mkdir_with_parents(WORKDIR, 0700);
424
425 test_tls_init(KEYFILE);
426 test_tls_psk_init(PSKFILE);
427
428 /* Simple initial test using Pre-Shared Keys. */
429 g_test_add_func("/qcrypto/tlssession/psk",
430 test_crypto_tls_session_psk);
431
432 /* More complex tests using X.509 certificates. */
433 # define TEST_SESS_REG(name, caCrt, \
434 serverCrt, clientCrt, \
435 expectServerFail, expectClientFail, \
436 hostname, wildcards) \
437 struct QCryptoTLSSessionTestData name = { \
438 caCrt, caCrt, serverCrt, clientCrt, \
439 expectServerFail, expectClientFail, \
440 hostname, wildcards \
441 }; \
442 g_test_add_data_func("/qcrypto/tlssession/" # name, \
443 &name, test_crypto_tls_session_x509); \
444
445
446 # define TEST_SESS_REG_EXT(name, serverCaCrt, clientCaCrt, \
447 serverCrt, clientCrt, \
448 expectServerFail, expectClientFail, \
449 hostname, wildcards) \
450 struct QCryptoTLSSessionTestData name = { \
451 serverCaCrt, clientCaCrt, serverCrt, clientCrt, \
452 expectServerFail, expectClientFail, \
453 hostname, wildcards \
454 }; \
455 g_test_add_data_func("/qcrypto/tlssession/" # name, \
456 &name, test_crypto_tls_session_x509); \
457
458 /* A perfect CA, perfect client & perfect server */
459
460 /* Basic:CA:critical */
461 TLS_ROOT_REQ(cacertreq,
462 "UK", "qemu CA", NULL, NULL, NULL, NULL,
463 true, true, true,
464 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
465 false, false, NULL, NULL,
466 0, 0);
467
468 TLS_ROOT_REQ(altcacertreq,
469 "UK", "qemu CA 1", NULL, NULL, NULL, NULL,
470 true, true, true,
471 false, false, 0,
472 false, false, NULL, NULL,
473 0, 0);
474
475 TLS_CERT_REQ(servercertreq, cacertreq,
476 "UK", "qemu.org", NULL, NULL, NULL, NULL,
477 true, true, false,
478 true, true,
479 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
480 true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
481 0, 0);
482 TLS_CERT_REQ(clientcertreq, cacertreq,
483 "UK", "qemu", NULL, NULL, NULL, NULL,
484 true, true, false,
485 true, true,
486 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
487 true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
488 0, 0);
489
490 TLS_CERT_REQ(clientcertaltreq, altcacertreq,
491 "UK", "qemu", NULL, NULL, NULL, NULL,
492 true, true, false,
493 true, true,
494 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
495 true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
496 0, 0);
497
498 TEST_SESS_REG(basicca, cacertreq.filename,
499 servercertreq.filename, clientcertreq.filename,
500 false, false, "qemu.org", NULL);
501 TEST_SESS_REG_EXT(differentca, cacertreq.filename,
502 altcacertreq.filename, servercertreq.filename,
503 clientcertaltreq.filename, true, true, "qemu.org", NULL);
504
505
506 /* When an altname is set, the CN is ignored, so it must be duplicated
507 * as an altname for it to match */
508 TLS_CERT_REQ(servercertalt1req, cacertreq,
509 "UK", "qemu.org", "www.qemu.org", "qemu.org",
510 "192.168.122.1", "fec0::dead:beaf",
511 true, true, false,
512 true, true,
513 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
514 true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
515 0, 0);
516 /* This intentionally doesn't replicate */
517 TLS_CERT_REQ(servercertalt2req, cacertreq,
518 "UK", "qemu.org", "www.qemu.org", "wiki.qemu.org",
519 "192.168.122.1", "fec0::dead:beaf",
520 true, true, false,
521 true, true,
522 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
523 true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
524 0, 0);
525
526 TEST_SESS_REG(altname1, cacertreq.filename,
527 servercertalt1req.filename, clientcertreq.filename,
528 false, false, "qemu.org", NULL);
529 TEST_SESS_REG(altname2, cacertreq.filename,
530 servercertalt1req.filename, clientcertreq.filename,
531 false, false, "www.qemu.org", NULL);
532 TEST_SESS_REG(altname3, cacertreq.filename,
533 servercertalt1req.filename, clientcertreq.filename,
534 false, true, "wiki.qemu.org", NULL);
535
536 TEST_SESS_REG(altname4, cacertreq.filename,
537 servercertalt1req.filename, clientcertreq.filename,
538 false, false, "192.168.122.1", NULL);
539 TEST_SESS_REG(altname5, cacertreq.filename,
540 servercertalt1req.filename, clientcertreq.filename,
541 false, false, "fec0::dead:beaf", NULL);
542
543 TEST_SESS_REG(altname6, cacertreq.filename,
544 servercertalt2req.filename, clientcertreq.filename,
545 false, true, "qemu.org", NULL);
546 TEST_SESS_REG(altname7, cacertreq.filename,
547 servercertalt2req.filename, clientcertreq.filename,
548 false, false, "www.qemu.org", NULL);
549 TEST_SESS_REG(altname8, cacertreq.filename,
550 servercertalt2req.filename, clientcertreq.filename,
551 false, false, "wiki.qemu.org", NULL);
552
553 const char *const wildcards1[] = {
554 "C=UK,CN=dogfood",
555 NULL,
556 };
557 const char *const wildcards2[] = {
558 "C=UK,CN=qemu",
559 NULL,
560 };
561 const char *const wildcards3[] = {
562 "C=UK,CN=dogfood",
563 "C=UK,CN=qemu",
564 NULL,
565 };
566 const char *const wildcards4[] = {
567 "C=UK,CN=qemustuff",
568 NULL,
569 };
570 const char *const wildcards5[] = {
571 "C=UK,CN=qemu*",
572 NULL,
573 };
574 const char *const wildcards6[] = {
575 "C=UK,CN=*emu*",
576 NULL,
577 };
578
579 TEST_SESS_REG(wildcard1, cacertreq.filename,
580 servercertreq.filename, clientcertreq.filename,
581 true, false, "qemu.org", wildcards1);
582 TEST_SESS_REG(wildcard2, cacertreq.filename,
583 servercertreq.filename, clientcertreq.filename,
584 false, false, "qemu.org", wildcards2);
585 TEST_SESS_REG(wildcard3, cacertreq.filename,
586 servercertreq.filename, clientcertreq.filename,
587 false, false, "qemu.org", wildcards3);
588 TEST_SESS_REG(wildcard4, cacertreq.filename,
589 servercertreq.filename, clientcertreq.filename,
590 true, false, "qemu.org", wildcards4);
591 TEST_SESS_REG(wildcard5, cacertreq.filename,
592 servercertreq.filename, clientcertreq.filename,
593 false, false, "qemu.org", wildcards5);
594 TEST_SESS_REG(wildcard6, cacertreq.filename,
595 servercertreq.filename, clientcertreq.filename,
596 false, false, "qemu.org", wildcards6);
597
598 TLS_ROOT_REQ(cacertrootreq,
599 "UK", "qemu root", NULL, NULL, NULL, NULL,
600 true, true, true,
601 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
602 false, false, NULL, NULL,
603 0, 0);
604 TLS_CERT_REQ(cacertlevel1areq, cacertrootreq,
605 "UK", "qemu level 1a", NULL, NULL, NULL, NULL,
606 true, true, true,
607 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
608 false, false, NULL, NULL,
609 0, 0);
610 TLS_CERT_REQ(cacertlevel1breq, cacertrootreq,
611 "UK", "qemu level 1b", NULL, NULL, NULL, NULL,
612 true, true, true,
613 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
614 false, false, NULL, NULL,
615 0, 0);
616 TLS_CERT_REQ(cacertlevel2areq, cacertlevel1areq,
617 "UK", "qemu level 2a", NULL, NULL, NULL, NULL,
618 true, true, true,
619 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
620 false, false, NULL, NULL,
621 0, 0);
622 TLS_CERT_REQ(servercertlevel3areq, cacertlevel2areq,
623 "UK", "qemu.org", NULL, NULL, NULL, NULL,
624 true, true, false,
625 true, true,
626 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
627 true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
628 0, 0);
629 TLS_CERT_REQ(clientcertlevel2breq, cacertlevel1breq,
630 "UK", "qemu client level 2b", NULL, NULL, NULL, NULL,
631 true, true, false,
632 true, true,
633 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
634 true, true, GNUTLS_KP_TLS_WWW_CLIENT, NULL,
635 0, 0);
636
637 gnutls_x509_crt_t certchain[] = {
638 cacertrootreq.crt,
639 cacertlevel1areq.crt,
640 cacertlevel1breq.crt,
641 cacertlevel2areq.crt,
642 };
643
644 test_tls_write_cert_chain(WORKDIR "cacertchain-sess.pem",
645 certchain,
646 G_N_ELEMENTS(certchain));
647
648 TEST_SESS_REG(cachain, WORKDIR "cacertchain-sess.pem",
649 servercertlevel3areq.filename, clientcertlevel2breq.filename,
650 false, false, "qemu.org", NULL);
651
652 ret = g_test_run();
653
654 test_tls_discard_cert(&clientcertreq);
655 test_tls_discard_cert(&clientcertaltreq);
656
657 test_tls_discard_cert(&servercertreq);
658 test_tls_discard_cert(&servercertalt1req);
659 test_tls_discard_cert(&servercertalt2req);
660
661 test_tls_discard_cert(&cacertreq);
662 test_tls_discard_cert(&altcacertreq);
663
664 test_tls_discard_cert(&cacertrootreq);
665 test_tls_discard_cert(&cacertlevel1areq);
666 test_tls_discard_cert(&cacertlevel1breq);
667 test_tls_discard_cert(&cacertlevel2areq);
668 test_tls_discard_cert(&servercertlevel3areq);
669 test_tls_discard_cert(&clientcertlevel2breq);
670 unlink(WORKDIR "cacertchain-sess.pem");
671
672 test_tls_psk_cleanup(PSKFILE);
673 test_tls_cleanup(KEYFILE);
674 rmdir(WORKDIR);
675
676 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
677 }
678