cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

test-crypto-tlssession.c (23764B)


      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_set_nonblock(channel[0]);
     94    qemu_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_set_nonblock(channel[0]);
    248    qemu_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                  servercertalt2req.filename, clientcertreq.filename,
    516                  false, true, "qemu.org", NULL);
    517    TEST_SESS_REG(altname5, cacertreq.filename,
    518                  servercertalt2req.filename, clientcertreq.filename,
    519                  false, false, "www.qemu.org", NULL);
    520    TEST_SESS_REG(altname6, cacertreq.filename,
    521                  servercertalt2req.filename, clientcertreq.filename,
    522                  false, false, "wiki.qemu.org", NULL);
    523
    524    const char *const wildcards1[] = {
    525        "C=UK,CN=dogfood",
    526        NULL,
    527    };
    528    const char *const wildcards2[] = {
    529        "C=UK,CN=qemu",
    530        NULL,
    531    };
    532    const char *const wildcards3[] = {
    533        "C=UK,CN=dogfood",
    534        "C=UK,CN=qemu",
    535        NULL,
    536    };
    537    const char *const wildcards4[] = {
    538        "C=UK,CN=qemustuff",
    539        NULL,
    540    };
    541    const char *const wildcards5[] = {
    542        "C=UK,CN=qemu*",
    543        NULL,
    544    };
    545    const char *const wildcards6[] = {
    546        "C=UK,CN=*emu*",
    547        NULL,
    548    };
    549
    550    TEST_SESS_REG(wildcard1, cacertreq.filename,
    551                  servercertreq.filename, clientcertreq.filename,
    552                  true, false, "qemu.org", wildcards1);
    553    TEST_SESS_REG(wildcard2, cacertreq.filename,
    554                  servercertreq.filename, clientcertreq.filename,
    555                  false, false, "qemu.org", wildcards2);
    556    TEST_SESS_REG(wildcard3, cacertreq.filename,
    557                  servercertreq.filename, clientcertreq.filename,
    558                  false, false, "qemu.org", wildcards3);
    559    TEST_SESS_REG(wildcard4, cacertreq.filename,
    560                  servercertreq.filename, clientcertreq.filename,
    561                  true, false, "qemu.org", wildcards4);
    562    TEST_SESS_REG(wildcard5, cacertreq.filename,
    563                  servercertreq.filename, clientcertreq.filename,
    564                  false, false, "qemu.org", wildcards5);
    565    TEST_SESS_REG(wildcard6, cacertreq.filename,
    566                  servercertreq.filename, clientcertreq.filename,
    567                  false, false, "qemu.org", wildcards6);
    568
    569    TLS_ROOT_REQ(cacertrootreq,
    570                 "UK", "qemu root", NULL, NULL, NULL, NULL,
    571                 true, true, true,
    572                 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
    573                 false, false, NULL, NULL,
    574                 0, 0);
    575    TLS_CERT_REQ(cacertlevel1areq, cacertrootreq,
    576                 "UK", "qemu level 1a", NULL, NULL, NULL, NULL,
    577                 true, true, true,
    578                 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
    579                 false, false, NULL, NULL,
    580                 0, 0);
    581    TLS_CERT_REQ(cacertlevel1breq, cacertrootreq,
    582                 "UK", "qemu level 1b", NULL, NULL, NULL, NULL,
    583                 true, true, true,
    584                 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
    585                 false, false, NULL, NULL,
    586                 0, 0);
    587    TLS_CERT_REQ(cacertlevel2areq, cacertlevel1areq,
    588                 "UK", "qemu level 2a", NULL, NULL, NULL, NULL,
    589                 true, true, true,
    590                 true, true, GNUTLS_KEY_KEY_CERT_SIGN,
    591                 false, false, NULL, NULL,
    592                 0, 0);
    593    TLS_CERT_REQ(servercertlevel3areq, cacertlevel2areq,
    594                 "UK", "qemu.org", NULL, NULL, NULL, NULL,
    595                 true, true, false,
    596                 true, true,
    597                 GNUTLS_KEY_DIGITAL_SIGNATURE | GNUTLS_KEY_KEY_ENCIPHERMENT,
    598                 true, true, GNUTLS_KP_TLS_WWW_SERVER, NULL,
    599                 0, 0);
    600    TLS_CERT_REQ(clientcertlevel2breq, cacertlevel1breq,
    601                 "UK", "qemu client level 2b", 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_CLIENT, NULL,
    606                 0, 0);
    607
    608    gnutls_x509_crt_t certchain[] = {
    609        cacertrootreq.crt,
    610        cacertlevel1areq.crt,
    611        cacertlevel1breq.crt,
    612        cacertlevel2areq.crt,
    613    };
    614
    615    test_tls_write_cert_chain(WORKDIR "cacertchain-sess.pem",
    616                              certchain,
    617                              G_N_ELEMENTS(certchain));
    618
    619    TEST_SESS_REG(cachain, WORKDIR "cacertchain-sess.pem",
    620                  servercertlevel3areq.filename, clientcertlevel2breq.filename,
    621                  false, false, "qemu.org", NULL);
    622
    623    ret = g_test_run();
    624
    625    test_tls_discard_cert(&clientcertreq);
    626    test_tls_discard_cert(&clientcertaltreq);
    627
    628    test_tls_discard_cert(&servercertreq);
    629    test_tls_discard_cert(&servercertalt1req);
    630    test_tls_discard_cert(&servercertalt2req);
    631
    632    test_tls_discard_cert(&cacertreq);
    633    test_tls_discard_cert(&altcacertreq);
    634
    635    test_tls_discard_cert(&cacertrootreq);
    636    test_tls_discard_cert(&cacertlevel1areq);
    637    test_tls_discard_cert(&cacertlevel1breq);
    638    test_tls_discard_cert(&cacertlevel2areq);
    639    test_tls_discard_cert(&servercertlevel3areq);
    640    test_tls_discard_cert(&clientcertlevel2breq);
    641    unlink(WORKDIR "cacertchain-sess.pem");
    642
    643    test_tls_psk_cleanup(PSKFILE);
    644    test_tls_cleanup(KEYFILE);
    645    rmdir(WORKDIR);
    646
    647    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
    648}