qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

test-crypto-tlssession.c (24188B)


      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)
     39 {
     40     int *fd = opaque;
     41 
     42     return write(*fd, buf, len);
     43 }
     44 
     45 static ssize_t testRead(char *buf, size_t len, void *opaque)
     46 {
     47     int *fd = opaque;
     48 
     49     return read(*fd, buf, len);
     50 }
     51 
     52 static 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 
     73 static 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 
    173 struct 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 
    184 static 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  */
    223 static 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     g_mkdir_with_parents(CLIENT_CERT_DIR, 0700);
    253     g_mkdir_with_parents(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 
    393 int 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     g_mkdir_with_parents(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 }