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