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