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 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 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 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 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 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 */ 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 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