xref: /openbmc/qemu/crypto/tlssession.c (revision 9726687f2fdfe7ae4a3014d78c2b2f639f75e303)
1d321e1e5SDaniel P. Berrange /*
2d321e1e5SDaniel P. Berrange  * QEMU crypto TLS session support
3d321e1e5SDaniel P. Berrange  *
4d321e1e5SDaniel P. Berrange  * Copyright (c) 2015 Red Hat, Inc.
5d321e1e5SDaniel P. Berrange  *
6d321e1e5SDaniel P. Berrange  * This library is free software; you can redistribute it and/or
7d321e1e5SDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
8d321e1e5SDaniel P. Berrange  * License as published by the Free Software Foundation; either
9b7cbb874SThomas Huth  * version 2.1 of the License, or (at your option) any later version.
10d321e1e5SDaniel P. Berrange  *
11d321e1e5SDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
12d321e1e5SDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13d321e1e5SDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14d321e1e5SDaniel P. Berrange  * Lesser General Public License for more details.
15d321e1e5SDaniel P. Berrange  *
16d321e1e5SDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
17d321e1e5SDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18d321e1e5SDaniel P. Berrange  *
19d321e1e5SDaniel P. Berrange  */
20d321e1e5SDaniel P. Berrange 
2142f7a448SPeter Maydell #include "qemu/osdep.h"
22d321e1e5SDaniel P. Berrange #include "crypto/tlssession.h"
23d321e1e5SDaniel P. Berrange #include "crypto/tlscredsanon.h"
24e1a6dc91SRichard W.M. Jones #include "crypto/tlscredspsk.h"
25d321e1e5SDaniel P. Berrange #include "crypto/tlscredsx509.h"
26da34e65cSMarkus Armbruster #include "qapi/error.h"
27b76806d4SDaniel P. Berrange #include "authz/base.h"
28678bcc3cSPhilippe Mathieu-Daudé #include "tlscredspriv.h"
29d321e1e5SDaniel P. Berrange #include "trace.h"
30d321e1e5SDaniel P. Berrange 
31d321e1e5SDaniel P. Berrange #ifdef CONFIG_GNUTLS
32d321e1e5SDaniel P. Berrange 
33d321e1e5SDaniel P. Berrange 
34d321e1e5SDaniel P. Berrange #include <gnutls/x509.h>
35d321e1e5SDaniel P. Berrange 
36d321e1e5SDaniel P. Berrange 
37d321e1e5SDaniel P. Berrange struct QCryptoTLSSession {
38d321e1e5SDaniel P. Berrange     QCryptoTLSCreds *creds;
39d321e1e5SDaniel P. Berrange     gnutls_session_t handle;
40d321e1e5SDaniel P. Berrange     char *hostname;
41b76806d4SDaniel P. Berrange     char *authzid;
42d321e1e5SDaniel P. Berrange     bool handshakeComplete;
43d321e1e5SDaniel P. Berrange     QCryptoTLSSessionWriteFunc writeFunc;
44d321e1e5SDaniel P. Berrange     QCryptoTLSSessionReadFunc readFunc;
45d321e1e5SDaniel P. Berrange     void *opaque;
46d321e1e5SDaniel P. Berrange     char *peername;
47*97f7bf11SDaniel P. Berrangé 
48*97f7bf11SDaniel P. Berrangé     /*
49*97f7bf11SDaniel P. Berrangé      * Allow concurrent reads and writes, so track
50*97f7bf11SDaniel P. Berrangé      * errors separately
51*97f7bf11SDaniel P. Berrangé      */
52*97f7bf11SDaniel P. Berrangé     Error *rerr;
53*97f7bf11SDaniel P. Berrangé     Error *werr;
54d321e1e5SDaniel P. Berrange };
55d321e1e5SDaniel P. Berrange 
56d321e1e5SDaniel P. Berrange 
57d321e1e5SDaniel P. Berrange void
qcrypto_tls_session_free(QCryptoTLSSession * session)58d321e1e5SDaniel P. Berrange qcrypto_tls_session_free(QCryptoTLSSession *session)
59d321e1e5SDaniel P. Berrange {
60d321e1e5SDaniel P. Berrange     if (!session) {
61d321e1e5SDaniel P. Berrange         return;
62d321e1e5SDaniel P. Berrange     }
63d321e1e5SDaniel P. Berrange 
64*97f7bf11SDaniel P. Berrangé     error_free(session->rerr);
65*97f7bf11SDaniel P. Berrangé     error_free(session->werr);
66*97f7bf11SDaniel P. Berrangé 
67d321e1e5SDaniel P. Berrange     gnutls_deinit(session->handle);
68d321e1e5SDaniel P. Berrange     g_free(session->hostname);
69d321e1e5SDaniel P. Berrange     g_free(session->peername);
70b76806d4SDaniel P. Berrange     g_free(session->authzid);
71d321e1e5SDaniel P. Berrange     object_unref(OBJECT(session->creds));
72d321e1e5SDaniel P. Berrange     g_free(session);
73d321e1e5SDaniel P. Berrange }
74d321e1e5SDaniel P. Berrange 
75d321e1e5SDaniel P. Berrange 
76d321e1e5SDaniel P. Berrange static ssize_t
qcrypto_tls_session_push(void * opaque,const void * buf,size_t len)77d321e1e5SDaniel P. Berrange qcrypto_tls_session_push(void *opaque, const void *buf, size_t len)
78d321e1e5SDaniel P. Berrange {
79d321e1e5SDaniel P. Berrange     QCryptoTLSSession *session = opaque;
80*97f7bf11SDaniel P. Berrangé     ssize_t ret;
81d321e1e5SDaniel P. Berrange 
82d321e1e5SDaniel P. Berrange     if (!session->writeFunc) {
83d321e1e5SDaniel P. Berrange         errno = EIO;
84d321e1e5SDaniel P. Berrange         return -1;
85d321e1e5SDaniel P. Berrange     };
86d321e1e5SDaniel P. Berrange 
87*97f7bf11SDaniel P. Berrangé     error_free(session->werr);
88*97f7bf11SDaniel P. Berrangé     session->werr = NULL;
89*97f7bf11SDaniel P. Berrangé 
90*97f7bf11SDaniel P. Berrangé     ret = session->writeFunc(buf, len, session->opaque, &session->werr);
91*97f7bf11SDaniel P. Berrangé     if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) {
92*97f7bf11SDaniel P. Berrangé         errno = EAGAIN;
93*97f7bf11SDaniel P. Berrangé         return -1;
94*97f7bf11SDaniel P. Berrangé     } else if (ret < 0) {
95*97f7bf11SDaniel P. Berrangé         errno = EIO;
96*97f7bf11SDaniel P. Berrangé         return -1;
97*97f7bf11SDaniel P. Berrangé     } else {
98*97f7bf11SDaniel P. Berrangé         return ret;
99*97f7bf11SDaniel P. Berrangé     }
100d321e1e5SDaniel P. Berrange }
101d321e1e5SDaniel P. Berrange 
102d321e1e5SDaniel P. Berrange 
103d321e1e5SDaniel P. Berrange static ssize_t
qcrypto_tls_session_pull(void * opaque,void * buf,size_t len)104d321e1e5SDaniel P. Berrange qcrypto_tls_session_pull(void *opaque, void *buf, size_t len)
105d321e1e5SDaniel P. Berrange {
106d321e1e5SDaniel P. Berrange     QCryptoTLSSession *session = opaque;
107*97f7bf11SDaniel P. Berrangé     ssize_t ret;
108d321e1e5SDaniel P. Berrange 
109d321e1e5SDaniel P. Berrange     if (!session->readFunc) {
110d321e1e5SDaniel P. Berrange         errno = EIO;
111d321e1e5SDaniel P. Berrange         return -1;
112d321e1e5SDaniel P. Berrange     };
113d321e1e5SDaniel P. Berrange 
114*97f7bf11SDaniel P. Berrangé     error_free(session->rerr);
115*97f7bf11SDaniel P. Berrangé     session->rerr = NULL;
116*97f7bf11SDaniel P. Berrangé 
117*97f7bf11SDaniel P. Berrangé     ret = session->readFunc(buf, len, session->opaque, &session->rerr);
118*97f7bf11SDaniel P. Berrangé     if (ret == QCRYPTO_TLS_SESSION_ERR_BLOCK) {
119*97f7bf11SDaniel P. Berrangé         errno = EAGAIN;
120*97f7bf11SDaniel P. Berrangé         return -1;
121*97f7bf11SDaniel P. Berrangé     } else if (ret < 0) {
122*97f7bf11SDaniel P. Berrangé         errno = EIO;
123*97f7bf11SDaniel P. Berrangé         return -1;
124*97f7bf11SDaniel P. Berrangé     } else {
125*97f7bf11SDaniel P. Berrangé         return ret;
126*97f7bf11SDaniel P. Berrangé     }
127d321e1e5SDaniel P. Berrange }
128d321e1e5SDaniel P. Berrange 
129e1a6dc91SRichard W.M. Jones #define TLS_PRIORITY_ADDITIONAL_ANON "+ANON-DH"
130a0722409SDaniel P. Berrangé #define TLS_PRIORITY_ADDITIONAL_PSK "+ECDHE-PSK:+DHE-PSK:+PSK"
131d321e1e5SDaniel P. Berrange 
132d321e1e5SDaniel P. Berrange QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds * creds,const char * hostname,const char * authzid,QCryptoTLSCredsEndpoint endpoint,Error ** errp)133d321e1e5SDaniel P. Berrange qcrypto_tls_session_new(QCryptoTLSCreds *creds,
134d321e1e5SDaniel P. Berrange                         const char *hostname,
135b76806d4SDaniel P. Berrange                         const char *authzid,
136d321e1e5SDaniel P. Berrange                         QCryptoTLSCredsEndpoint endpoint,
137d321e1e5SDaniel P. Berrange                         Error **errp)
138d321e1e5SDaniel P. Berrange {
139d321e1e5SDaniel P. Berrange     QCryptoTLSSession *session;
140d321e1e5SDaniel P. Berrange     int ret;
141d321e1e5SDaniel P. Berrange 
142d321e1e5SDaniel P. Berrange     session = g_new0(QCryptoTLSSession, 1);
143d321e1e5SDaniel P. Berrange     trace_qcrypto_tls_session_new(
144d321e1e5SDaniel P. Berrange         session, creds, hostname ? hostname : "<none>",
145b76806d4SDaniel P. Berrange         authzid ? authzid : "<none>", endpoint);
146d321e1e5SDaniel P. Berrange 
147d321e1e5SDaniel P. Berrange     if (hostname) {
148d321e1e5SDaniel P. Berrange         session->hostname = g_strdup(hostname);
149d321e1e5SDaniel P. Berrange     }
150b76806d4SDaniel P. Berrange     if (authzid) {
151b76806d4SDaniel P. Berrange         session->authzid = g_strdup(authzid);
152d321e1e5SDaniel P. Berrange     }
153d321e1e5SDaniel P. Berrange     session->creds = creds;
154d321e1e5SDaniel P. Berrange     object_ref(OBJECT(creds));
155d321e1e5SDaniel P. Berrange 
156d321e1e5SDaniel P. Berrange     if (creds->endpoint != endpoint) {
157d321e1e5SDaniel P. Berrange         error_setg(errp, "Credentials endpoint doesn't match session");
158d321e1e5SDaniel P. Berrange         goto error;
159d321e1e5SDaniel P. Berrange     }
160d321e1e5SDaniel P. Berrange 
161d321e1e5SDaniel P. Berrange     if (endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
162d321e1e5SDaniel P. Berrange         ret = gnutls_init(&session->handle, GNUTLS_SERVER);
163d321e1e5SDaniel P. Berrange     } else {
164d321e1e5SDaniel P. Berrange         ret = gnutls_init(&session->handle, GNUTLS_CLIENT);
165d321e1e5SDaniel P. Berrange     }
166d321e1e5SDaniel P. Berrange     if (ret < 0) {
167d321e1e5SDaniel P. Berrange         error_setg(errp, "Cannot initialize TLS session: %s",
168d321e1e5SDaniel P. Berrange                    gnutls_strerror(ret));
169d321e1e5SDaniel P. Berrange         goto error;
170d321e1e5SDaniel P. Berrange     }
171d321e1e5SDaniel P. Berrange 
172d321e1e5SDaniel P. Berrange     if (object_dynamic_cast(OBJECT(creds),
173d321e1e5SDaniel P. Berrange                             TYPE_QCRYPTO_TLS_CREDS_ANON)) {
174d321e1e5SDaniel P. Berrange         QCryptoTLSCredsAnon *acreds = QCRYPTO_TLS_CREDS_ANON(creds);
17513f12430SDaniel P. Berrange         char *prio;
176d321e1e5SDaniel P. Berrange 
17713f12430SDaniel P. Berrange         if (creds->priority != NULL) {
178e1a6dc91SRichard W.M. Jones             prio = g_strdup_printf("%s:%s",
179e1a6dc91SRichard W.M. Jones                                    creds->priority,
180e1a6dc91SRichard W.M. Jones                                    TLS_PRIORITY_ADDITIONAL_ANON);
18113f12430SDaniel P. Berrange         } else {
182e1a6dc91SRichard W.M. Jones             prio = g_strdup(CONFIG_TLS_PRIORITY ":"
183e1a6dc91SRichard W.M. Jones                             TLS_PRIORITY_ADDITIONAL_ANON);
18413f12430SDaniel P. Berrange         }
18513f12430SDaniel P. Berrange 
18613f12430SDaniel P. Berrange         ret = gnutls_priority_set_direct(session->handle, prio, NULL);
187d321e1e5SDaniel P. Berrange         if (ret < 0) {
18813f12430SDaniel P. Berrange             error_setg(errp, "Unable to set TLS session priority %s: %s",
18913f12430SDaniel P. Berrange                        prio, gnutls_strerror(ret));
19013f12430SDaniel P. Berrange             g_free(prio);
191d321e1e5SDaniel P. Berrange             goto error;
192d321e1e5SDaniel P. Berrange         }
19313f12430SDaniel P. Berrange         g_free(prio);
194d321e1e5SDaniel P. Berrange         if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
195d321e1e5SDaniel P. Berrange             ret = gnutls_credentials_set(session->handle,
196d321e1e5SDaniel P. Berrange                                          GNUTLS_CRD_ANON,
197d321e1e5SDaniel P. Berrange                                          acreds->data.server);
198d321e1e5SDaniel P. Berrange         } else {
199d321e1e5SDaniel P. Berrange             ret = gnutls_credentials_set(session->handle,
200d321e1e5SDaniel P. Berrange                                          GNUTLS_CRD_ANON,
201d321e1e5SDaniel P. Berrange                                          acreds->data.client);
202d321e1e5SDaniel P. Berrange         }
203d321e1e5SDaniel P. Berrange         if (ret < 0) {
204d321e1e5SDaniel P. Berrange             error_setg(errp, "Cannot set session credentials: %s",
205d321e1e5SDaniel P. Berrange                        gnutls_strerror(ret));
206d321e1e5SDaniel P. Berrange             goto error;
207d321e1e5SDaniel P. Berrange         }
208d321e1e5SDaniel P. Berrange     } else if (object_dynamic_cast(OBJECT(creds),
209e1a6dc91SRichard W.M. Jones                                    TYPE_QCRYPTO_TLS_CREDS_PSK)) {
210e1a6dc91SRichard W.M. Jones         QCryptoTLSCredsPSK *pcreds = QCRYPTO_TLS_CREDS_PSK(creds);
211e1a6dc91SRichard W.M. Jones         char *prio;
212e1a6dc91SRichard W.M. Jones 
213e1a6dc91SRichard W.M. Jones         if (creds->priority != NULL) {
214e1a6dc91SRichard W.M. Jones             prio = g_strdup_printf("%s:%s",
215e1a6dc91SRichard W.M. Jones                                    creds->priority,
216e1a6dc91SRichard W.M. Jones                                    TLS_PRIORITY_ADDITIONAL_PSK);
217e1a6dc91SRichard W.M. Jones         } else {
218e1a6dc91SRichard W.M. Jones             prio = g_strdup(CONFIG_TLS_PRIORITY ":"
219e1a6dc91SRichard W.M. Jones                             TLS_PRIORITY_ADDITIONAL_PSK);
220e1a6dc91SRichard W.M. Jones         }
221e1a6dc91SRichard W.M. Jones 
222e1a6dc91SRichard W.M. Jones         ret = gnutls_priority_set_direct(session->handle, prio, NULL);
223e1a6dc91SRichard W.M. Jones         if (ret < 0) {
224e1a6dc91SRichard W.M. Jones             error_setg(errp, "Unable to set TLS session priority %s: %s",
225e1a6dc91SRichard W.M. Jones                        prio, gnutls_strerror(ret));
226e1a6dc91SRichard W.M. Jones             g_free(prio);
227e1a6dc91SRichard W.M. Jones             goto error;
228e1a6dc91SRichard W.M. Jones         }
229e1a6dc91SRichard W.M. Jones         g_free(prio);
230e1a6dc91SRichard W.M. Jones         if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
231e1a6dc91SRichard W.M. Jones             ret = gnutls_credentials_set(session->handle,
232e1a6dc91SRichard W.M. Jones                                          GNUTLS_CRD_PSK,
233e1a6dc91SRichard W.M. Jones                                          pcreds->data.server);
234e1a6dc91SRichard W.M. Jones         } else {
235e1a6dc91SRichard W.M. Jones             ret = gnutls_credentials_set(session->handle,
236e1a6dc91SRichard W.M. Jones                                          GNUTLS_CRD_PSK,
237e1a6dc91SRichard W.M. Jones                                          pcreds->data.client);
238e1a6dc91SRichard W.M. Jones         }
239e1a6dc91SRichard W.M. Jones         if (ret < 0) {
240e1a6dc91SRichard W.M. Jones             error_setg(errp, "Cannot set session credentials: %s",
241e1a6dc91SRichard W.M. Jones                        gnutls_strerror(ret));
242e1a6dc91SRichard W.M. Jones             goto error;
243e1a6dc91SRichard W.M. Jones         }
244e1a6dc91SRichard W.M. Jones     } else if (object_dynamic_cast(OBJECT(creds),
245d321e1e5SDaniel P. Berrange                                    TYPE_QCRYPTO_TLS_CREDS_X509)) {
246d321e1e5SDaniel P. Berrange         QCryptoTLSCredsX509 *tcreds = QCRYPTO_TLS_CREDS_X509(creds);
24713f12430SDaniel P. Berrange         const char *prio = creds->priority;
24813f12430SDaniel P. Berrange         if (!prio) {
249a1c5e949SDaniel P. Berrange             prio = CONFIG_TLS_PRIORITY;
25013f12430SDaniel P. Berrange         }
251d321e1e5SDaniel P. Berrange 
25213f12430SDaniel P. Berrange         ret = gnutls_priority_set_direct(session->handle, prio, NULL);
253d321e1e5SDaniel P. Berrange         if (ret < 0) {
25413f12430SDaniel P. Berrange             error_setg(errp, "Cannot set default TLS session priority %s: %s",
25513f12430SDaniel P. Berrange                        prio, gnutls_strerror(ret));
256d321e1e5SDaniel P. Berrange             goto error;
257d321e1e5SDaniel P. Berrange         }
258d321e1e5SDaniel P. Berrange         ret = gnutls_credentials_set(session->handle,
259d321e1e5SDaniel P. Berrange                                      GNUTLS_CRD_CERTIFICATE,
260d321e1e5SDaniel P. Berrange                                      tcreds->data);
261d321e1e5SDaniel P. Berrange         if (ret < 0) {
262d321e1e5SDaniel P. Berrange             error_setg(errp, "Cannot set session credentials: %s",
263d321e1e5SDaniel P. Berrange                        gnutls_strerror(ret));
264d321e1e5SDaniel P. Berrange             goto error;
265d321e1e5SDaniel P. Berrange         }
266d321e1e5SDaniel P. Berrange 
267d321e1e5SDaniel P. Berrange         if (creds->endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
268d321e1e5SDaniel P. Berrange             /* This requests, but does not enforce a client cert.
269d321e1e5SDaniel P. Berrange              * The cert checking code later does enforcement */
270d321e1e5SDaniel P. Berrange             gnutls_certificate_server_set_request(session->handle,
271d321e1e5SDaniel P. Berrange                                                   GNUTLS_CERT_REQUEST);
272d321e1e5SDaniel P. Berrange         }
273d321e1e5SDaniel P. Berrange     } else {
274d321e1e5SDaniel P. Berrange         error_setg(errp, "Unsupported TLS credentials type %s",
275d321e1e5SDaniel P. Berrange                    object_get_typename(OBJECT(creds)));
276d321e1e5SDaniel P. Berrange         goto error;
277d321e1e5SDaniel P. Berrange     }
278d321e1e5SDaniel P. Berrange 
279d321e1e5SDaniel P. Berrange     gnutls_transport_set_ptr(session->handle, session);
280d321e1e5SDaniel P. Berrange     gnutls_transport_set_push_function(session->handle,
281d321e1e5SDaniel P. Berrange                                        qcrypto_tls_session_push);
282d321e1e5SDaniel P. Berrange     gnutls_transport_set_pull_function(session->handle,
283d321e1e5SDaniel P. Berrange                                        qcrypto_tls_session_pull);
284d321e1e5SDaniel P. Berrange 
285d321e1e5SDaniel P. Berrange     return session;
286d321e1e5SDaniel P. Berrange 
287d321e1e5SDaniel P. Berrange  error:
288d321e1e5SDaniel P. Berrange     qcrypto_tls_session_free(session);
289d321e1e5SDaniel P. Berrange     return NULL;
290d321e1e5SDaniel P. Berrange }
291d321e1e5SDaniel P. Berrange 
292d321e1e5SDaniel P. Berrange static int
qcrypto_tls_session_check_certificate(QCryptoTLSSession * session,Error ** errp)293d321e1e5SDaniel P. Berrange qcrypto_tls_session_check_certificate(QCryptoTLSSession *session,
294d321e1e5SDaniel P. Berrange                                       Error **errp)
295d321e1e5SDaniel P. Berrange {
296d321e1e5SDaniel P. Berrange     int ret;
297d321e1e5SDaniel P. Berrange     unsigned int status;
298d321e1e5SDaniel P. Berrange     const gnutls_datum_t *certs;
299d321e1e5SDaniel P. Berrange     unsigned int nCerts, i;
300d321e1e5SDaniel P. Berrange     time_t now;
301d321e1e5SDaniel P. Berrange     gnutls_x509_crt_t cert = NULL;
302b76806d4SDaniel P. Berrange     Error *err = NULL;
303d321e1e5SDaniel P. Berrange 
304d321e1e5SDaniel P. Berrange     now = time(NULL);
305d321e1e5SDaniel P. Berrange     if (now == ((time_t)-1)) {
306d321e1e5SDaniel P. Berrange         error_setg_errno(errp, errno, "Cannot get current time");
307d321e1e5SDaniel P. Berrange         return -1;
308d321e1e5SDaniel P. Berrange     }
309d321e1e5SDaniel P. Berrange 
310d321e1e5SDaniel P. Berrange     ret = gnutls_certificate_verify_peers2(session->handle, &status);
311d321e1e5SDaniel P. Berrange     if (ret < 0) {
312d321e1e5SDaniel P. Berrange         error_setg(errp, "Verify failed: %s", gnutls_strerror(ret));
313d321e1e5SDaniel P. Berrange         return -1;
314d321e1e5SDaniel P. Berrange     }
315d321e1e5SDaniel P. Berrange 
316d321e1e5SDaniel P. Berrange     if (status != 0) {
317d321e1e5SDaniel P. Berrange         const char *reason = "Invalid certificate";
318d321e1e5SDaniel P. Berrange 
319d321e1e5SDaniel P. Berrange         if (status & GNUTLS_CERT_INVALID) {
320d321e1e5SDaniel P. Berrange             reason = "The certificate is not trusted";
321d321e1e5SDaniel P. Berrange         }
322d321e1e5SDaniel P. Berrange 
323d321e1e5SDaniel P. Berrange         if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) {
324d321e1e5SDaniel P. Berrange             reason = "The certificate hasn't got a known issuer";
325d321e1e5SDaniel P. Berrange         }
326d321e1e5SDaniel P. Berrange 
327d321e1e5SDaniel P. Berrange         if (status & GNUTLS_CERT_REVOKED) {
328d321e1e5SDaniel P. Berrange             reason = "The certificate has been revoked";
329d321e1e5SDaniel P. Berrange         }
330d321e1e5SDaniel P. Berrange 
331d321e1e5SDaniel P. Berrange         if (status & GNUTLS_CERT_INSECURE_ALGORITHM) {
332d321e1e5SDaniel P. Berrange             reason = "The certificate uses an insecure algorithm";
333d321e1e5SDaniel P. Berrange         }
334d321e1e5SDaniel P. Berrange 
335d321e1e5SDaniel P. Berrange         error_setg(errp, "%s", reason);
336d321e1e5SDaniel P. Berrange         return -1;
337d321e1e5SDaniel P. Berrange     }
338d321e1e5SDaniel P. Berrange 
339d321e1e5SDaniel P. Berrange     certs = gnutls_certificate_get_peers(session->handle, &nCerts);
340d321e1e5SDaniel P. Berrange     if (!certs) {
341d321e1e5SDaniel P. Berrange         error_setg(errp, "No certificate peers");
342d321e1e5SDaniel P. Berrange         return -1;
343d321e1e5SDaniel P. Berrange     }
344d321e1e5SDaniel P. Berrange 
345d321e1e5SDaniel P. Berrange     for (i = 0; i < nCerts; i++) {
346d321e1e5SDaniel P. Berrange         ret = gnutls_x509_crt_init(&cert);
347d321e1e5SDaniel P. Berrange         if (ret < 0) {
348d321e1e5SDaniel P. Berrange             error_setg(errp, "Cannot initialize certificate: %s",
349d321e1e5SDaniel P. Berrange                        gnutls_strerror(ret));
350d321e1e5SDaniel P. Berrange             return -1;
351d321e1e5SDaniel P. Berrange         }
352d321e1e5SDaniel P. Berrange 
353d321e1e5SDaniel P. Berrange         ret = gnutls_x509_crt_import(cert, &certs[i], GNUTLS_X509_FMT_DER);
354d321e1e5SDaniel P. Berrange         if (ret < 0) {
355d321e1e5SDaniel P. Berrange             error_setg(errp, "Cannot import certificate: %s",
356d321e1e5SDaniel P. Berrange                        gnutls_strerror(ret));
357d321e1e5SDaniel P. Berrange             goto error;
358d321e1e5SDaniel P. Berrange         }
359d321e1e5SDaniel P. Berrange 
360d321e1e5SDaniel P. Berrange         if (gnutls_x509_crt_get_expiration_time(cert) < now) {
361d321e1e5SDaniel P. Berrange             error_setg(errp, "The certificate has expired");
362d321e1e5SDaniel P. Berrange             goto error;
363d321e1e5SDaniel P. Berrange         }
364d321e1e5SDaniel P. Berrange 
365d321e1e5SDaniel P. Berrange         if (gnutls_x509_crt_get_activation_time(cert) > now) {
366d321e1e5SDaniel P. Berrange             error_setg(errp, "The certificate is not yet activated");
367d321e1e5SDaniel P. Berrange             goto error;
368d321e1e5SDaniel P. Berrange         }
369d321e1e5SDaniel P. Berrange 
370d321e1e5SDaniel P. Berrange         if (gnutls_x509_crt_get_activation_time(cert) > now) {
371d321e1e5SDaniel P. Berrange             error_setg(errp, "The certificate is not yet activated");
372d321e1e5SDaniel P. Berrange             goto error;
373d321e1e5SDaniel P. Berrange         }
374d321e1e5SDaniel P. Berrange 
375d321e1e5SDaniel P. Berrange         if (i == 0) {
376d321e1e5SDaniel P. Berrange             size_t dnameSize = 1024;
377d321e1e5SDaniel P. Berrange             session->peername = g_malloc(dnameSize);
378d321e1e5SDaniel P. Berrange         requery:
379d321e1e5SDaniel P. Berrange             ret = gnutls_x509_crt_get_dn(cert, session->peername, &dnameSize);
380d321e1e5SDaniel P. Berrange             if (ret < 0) {
381d321e1e5SDaniel P. Berrange                 if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER) {
382d321e1e5SDaniel P. Berrange                     session->peername = g_realloc(session->peername,
383d321e1e5SDaniel P. Berrange                                                   dnameSize);
384d321e1e5SDaniel P. Berrange                     goto requery;
385d321e1e5SDaniel P. Berrange                 }
386d321e1e5SDaniel P. Berrange                 error_setg(errp, "Cannot get client distinguished name: %s",
387d321e1e5SDaniel P. Berrange                            gnutls_strerror(ret));
388d321e1e5SDaniel P. Berrange                 goto error;
389d321e1e5SDaniel P. Berrange             }
390b76806d4SDaniel P. Berrange             if (session->authzid) {
391b76806d4SDaniel P. Berrange                 bool allow;
392b76806d4SDaniel P. Berrange 
393b76806d4SDaniel P. Berrange                 allow = qauthz_is_allowed_by_id(session->authzid,
394b76806d4SDaniel P. Berrange                                                 session->peername, &err);
395b76806d4SDaniel P. Berrange                 if (err) {
396b76806d4SDaniel P. Berrange                     error_propagate(errp, err);
397d321e1e5SDaniel P. Berrange                     goto error;
398d321e1e5SDaniel P. Berrange                 }
399d321e1e5SDaniel P. Berrange                 if (!allow) {
400b76806d4SDaniel P. Berrange                     error_setg(errp, "TLS x509 authz check for %s is denied",
4016ef8cd7aSDaniel P. Berrange                                session->peername);
402d321e1e5SDaniel P. Berrange                     goto error;
403d321e1e5SDaniel P. Berrange                 }
404d321e1e5SDaniel P. Berrange             }
405d321e1e5SDaniel P. Berrange             if (session->hostname) {
406d321e1e5SDaniel P. Berrange                 if (!gnutls_x509_crt_check_hostname(cert, session->hostname)) {
407d321e1e5SDaniel P. Berrange                     error_setg(errp,
408d321e1e5SDaniel P. Berrange                                "Certificate does not match the hostname %s",
409d321e1e5SDaniel P. Berrange                                session->hostname);
410d321e1e5SDaniel P. Berrange                     goto error;
411d321e1e5SDaniel P. Berrange                 }
412d41997e4SDaniel P. Berrangé             } else {
413d41997e4SDaniel P. Berrangé                 if (session->creds->endpoint ==
414d41997e4SDaniel P. Berrangé                     QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
415d41997e4SDaniel P. Berrangé                     error_setg(errp, "No hostname for certificate validation");
416d41997e4SDaniel P. Berrangé                     goto error;
417d41997e4SDaniel P. Berrangé                 }
418d321e1e5SDaniel P. Berrange             }
419d321e1e5SDaniel P. Berrange         }
420d321e1e5SDaniel P. Berrange 
421d321e1e5SDaniel P. Berrange         gnutls_x509_crt_deinit(cert);
422d321e1e5SDaniel P. Berrange     }
423d321e1e5SDaniel P. Berrange 
424d321e1e5SDaniel P. Berrange     return 0;
425d321e1e5SDaniel P. Berrange 
426d321e1e5SDaniel P. Berrange  error:
427d321e1e5SDaniel P. Berrange     gnutls_x509_crt_deinit(cert);
428d321e1e5SDaniel P. Berrange     return -1;
429d321e1e5SDaniel P. Berrange }
430d321e1e5SDaniel P. Berrange 
431d321e1e5SDaniel P. Berrange 
432d321e1e5SDaniel P. Berrange int
qcrypto_tls_session_check_credentials(QCryptoTLSSession * session,Error ** errp)433d321e1e5SDaniel P. Berrange qcrypto_tls_session_check_credentials(QCryptoTLSSession *session,
434d321e1e5SDaniel P. Berrange                                       Error **errp)
435d321e1e5SDaniel P. Berrange {
436d321e1e5SDaniel P. Berrange     if (object_dynamic_cast(OBJECT(session->creds),
437d321e1e5SDaniel P. Berrange                             TYPE_QCRYPTO_TLS_CREDS_ANON)) {
438b57482d7SDaniel P. Berrange         trace_qcrypto_tls_session_check_creds(session, "nop");
439d321e1e5SDaniel P. Berrange         return 0;
440d321e1e5SDaniel P. Berrange     } else if (object_dynamic_cast(OBJECT(session->creds),
441e1a6dc91SRichard W.M. Jones                             TYPE_QCRYPTO_TLS_CREDS_PSK)) {
442e1a6dc91SRichard W.M. Jones         trace_qcrypto_tls_session_check_creds(session, "nop");
443e1a6dc91SRichard W.M. Jones         return 0;
444e1a6dc91SRichard W.M. Jones     } else if (object_dynamic_cast(OBJECT(session->creds),
445d321e1e5SDaniel P. Berrange                             TYPE_QCRYPTO_TLS_CREDS_X509)) {
446d321e1e5SDaniel P. Berrange         if (session->creds->verifyPeer) {
447b57482d7SDaniel P. Berrange             int ret = qcrypto_tls_session_check_certificate(session,
448d321e1e5SDaniel P. Berrange                                                             errp);
449b57482d7SDaniel P. Berrange             trace_qcrypto_tls_session_check_creds(session,
450b57482d7SDaniel P. Berrange                                                   ret == 0 ? "pass" : "fail");
451b57482d7SDaniel P. Berrange             return ret;
452d321e1e5SDaniel P. Berrange         } else {
453b57482d7SDaniel P. Berrange             trace_qcrypto_tls_session_check_creds(session, "skip");
454d321e1e5SDaniel P. Berrange             return 0;
455d321e1e5SDaniel P. Berrange         }
456d321e1e5SDaniel P. Berrange     } else {
457b57482d7SDaniel P. Berrange         trace_qcrypto_tls_session_check_creds(session, "error");
458d321e1e5SDaniel P. Berrange         error_setg(errp, "Unexpected credential type %s",
459d321e1e5SDaniel P. Berrange                    object_get_typename(OBJECT(session->creds)));
460d321e1e5SDaniel P. Berrange         return -1;
461d321e1e5SDaniel P. Berrange     }
462d321e1e5SDaniel P. Berrange }
463d321e1e5SDaniel P. Berrange 
464d321e1e5SDaniel P. Berrange 
465d321e1e5SDaniel P. Berrange void
qcrypto_tls_session_set_callbacks(QCryptoTLSSession * session,QCryptoTLSSessionWriteFunc writeFunc,QCryptoTLSSessionReadFunc readFunc,void * opaque)466d321e1e5SDaniel P. Berrange qcrypto_tls_session_set_callbacks(QCryptoTLSSession *session,
467d321e1e5SDaniel P. Berrange                                   QCryptoTLSSessionWriteFunc writeFunc,
468d321e1e5SDaniel P. Berrange                                   QCryptoTLSSessionReadFunc readFunc,
469d321e1e5SDaniel P. Berrange                                   void *opaque)
470d321e1e5SDaniel P. Berrange {
471d321e1e5SDaniel P. Berrange     session->writeFunc = writeFunc;
472d321e1e5SDaniel P. Berrange     session->readFunc = readFunc;
473d321e1e5SDaniel P. Berrange     session->opaque = opaque;
474d321e1e5SDaniel P. Berrange }
475d321e1e5SDaniel P. Berrange 
476d321e1e5SDaniel P. Berrange 
477d321e1e5SDaniel P. Berrange ssize_t
qcrypto_tls_session_write(QCryptoTLSSession * session,const char * buf,size_t len,Error ** errp)478d321e1e5SDaniel P. Berrange qcrypto_tls_session_write(QCryptoTLSSession *session,
479d321e1e5SDaniel P. Berrange                           const char *buf,
48057941c9cSDaniel P. Berrangé                           size_t len,
48157941c9cSDaniel P. Berrangé                           Error **errp)
482d321e1e5SDaniel P. Berrange {
483d321e1e5SDaniel P. Berrange     ssize_t ret = gnutls_record_send(session->handle, buf, len);
484d321e1e5SDaniel P. Berrange 
485d321e1e5SDaniel P. Berrange     if (ret < 0) {
48657941c9cSDaniel P. Berrangé         if (ret == GNUTLS_E_AGAIN) {
48757941c9cSDaniel P. Berrangé             return QCRYPTO_TLS_SESSION_ERR_BLOCK;
48857941c9cSDaniel P. Berrangé         } else {
489*97f7bf11SDaniel P. Berrangé             if (session->werr) {
490*97f7bf11SDaniel P. Berrangé                 error_propagate(errp, session->werr);
491*97f7bf11SDaniel P. Berrangé                 session->werr = NULL;
492*97f7bf11SDaniel P. Berrangé             } else {
49357941c9cSDaniel P. Berrangé                 error_setg(errp,
49457941c9cSDaniel P. Berrangé                            "Cannot write to TLS channel: %s",
49557941c9cSDaniel P. Berrangé                            gnutls_strerror(ret));
496*97f7bf11SDaniel P. Berrangé             }
49757941c9cSDaniel P. Berrangé             return -1;
498d321e1e5SDaniel P. Berrange         }
499d321e1e5SDaniel P. Berrange     }
500d321e1e5SDaniel P. Berrange 
501d321e1e5SDaniel P. Berrange     return ret;
502d321e1e5SDaniel P. Berrange }
503d321e1e5SDaniel P. Berrange 
504d321e1e5SDaniel P. Berrange 
505d321e1e5SDaniel P. Berrange ssize_t
qcrypto_tls_session_read(QCryptoTLSSession * session,char * buf,size_t len,bool gracefulTermination,Error ** errp)506d321e1e5SDaniel P. Berrange qcrypto_tls_session_read(QCryptoTLSSession *session,
507d321e1e5SDaniel P. Berrange                          char *buf,
50857941c9cSDaniel P. Berrangé                          size_t len,
50957941c9cSDaniel P. Berrangé                          bool gracefulTermination,
51057941c9cSDaniel P. Berrangé                          Error **errp)
511d321e1e5SDaniel P. Berrange {
512d321e1e5SDaniel P. Berrange     ssize_t ret = gnutls_record_recv(session->handle, buf, len);
513d321e1e5SDaniel P. Berrange 
514d321e1e5SDaniel P. Berrange     if (ret < 0) {
51557941c9cSDaniel P. Berrangé         if (ret == GNUTLS_E_AGAIN) {
51657941c9cSDaniel P. Berrangé             return QCRYPTO_TLS_SESSION_ERR_BLOCK;
51757941c9cSDaniel P. Berrangé         } else if ((ret == GNUTLS_E_PREMATURE_TERMINATION) &&
51857941c9cSDaniel P. Berrangé                    gracefulTermination){
51957941c9cSDaniel P. Berrangé             return 0;
52057941c9cSDaniel P. Berrangé         } else {
521*97f7bf11SDaniel P. Berrangé             if (session->rerr) {
522*97f7bf11SDaniel P. Berrangé                 error_propagate(errp, session->rerr);
523*97f7bf11SDaniel P. Berrangé                 session->rerr = NULL;
524*97f7bf11SDaniel P. Berrangé             } else {
52557941c9cSDaniel P. Berrangé                 error_setg(errp,
52657941c9cSDaniel P. Berrangé                            "Cannot read from TLS channel: %s",
52757941c9cSDaniel P. Berrangé                            gnutls_strerror(ret));
528*97f7bf11SDaniel P. Berrangé             }
52957941c9cSDaniel P. Berrangé             return -1;
530d321e1e5SDaniel P. Berrange         }
531d321e1e5SDaniel P. Berrange     }
532d321e1e5SDaniel P. Berrange 
533d321e1e5SDaniel P. Berrange     return ret;
534d321e1e5SDaniel P. Berrange }
535d321e1e5SDaniel P. Berrange 
536d321e1e5SDaniel P. Berrange 
53733ee0d8eSAntoine Damhet size_t
qcrypto_tls_session_check_pending(QCryptoTLSSession * session)53833ee0d8eSAntoine Damhet qcrypto_tls_session_check_pending(QCryptoTLSSession *session)
53933ee0d8eSAntoine Damhet {
54033ee0d8eSAntoine Damhet     return gnutls_record_check_pending(session->handle);
54133ee0d8eSAntoine Damhet }
54233ee0d8eSAntoine Damhet 
54333ee0d8eSAntoine Damhet 
544d321e1e5SDaniel P. Berrange int
qcrypto_tls_session_handshake(QCryptoTLSSession * session,Error ** errp)545d321e1e5SDaniel P. Berrange qcrypto_tls_session_handshake(QCryptoTLSSession *session,
546d321e1e5SDaniel P. Berrange                               Error **errp)
547d321e1e5SDaniel P. Berrange {
548d321e1e5SDaniel P. Berrange     int ret = gnutls_handshake(session->handle);
549d321e1e5SDaniel P. Berrange     if (ret == 0) {
550d321e1e5SDaniel P. Berrange         session->handshakeComplete = true;
551d321e1e5SDaniel P. Berrange     } else {
552d321e1e5SDaniel P. Berrange         if (ret == GNUTLS_E_INTERRUPTED ||
553d321e1e5SDaniel P. Berrange             ret == GNUTLS_E_AGAIN) {
554d321e1e5SDaniel P. Berrange             ret = 1;
555d321e1e5SDaniel P. Berrange         } else {
556*97f7bf11SDaniel P. Berrangé             if (session->rerr || session->werr) {
557*97f7bf11SDaniel P. Berrangé                 error_setg(errp, "TLS handshake failed: %s: %s",
558*97f7bf11SDaniel P. Berrangé                            gnutls_strerror(ret),
559*97f7bf11SDaniel P. Berrangé                            error_get_pretty(session->rerr ?
560*97f7bf11SDaniel P. Berrangé                                             session->rerr : session->werr));
561*97f7bf11SDaniel P. Berrangé             } else {
562d321e1e5SDaniel P. Berrange                 error_setg(errp, "TLS handshake failed: %s",
563d321e1e5SDaniel P. Berrange                            gnutls_strerror(ret));
564*97f7bf11SDaniel P. Berrangé             }
565d321e1e5SDaniel P. Berrange             ret = -1;
566d321e1e5SDaniel P. Berrange         }
567d321e1e5SDaniel P. Berrange     }
568*97f7bf11SDaniel P. Berrangé     error_free(session->rerr);
569*97f7bf11SDaniel P. Berrangé     error_free(session->werr);
570*97f7bf11SDaniel P. Berrangé     session->rerr = session->werr = NULL;
571d321e1e5SDaniel P. Berrange 
572d321e1e5SDaniel P. Berrange     return ret;
573d321e1e5SDaniel P. Berrange }
574d321e1e5SDaniel P. Berrange 
575d321e1e5SDaniel P. Berrange 
576d321e1e5SDaniel P. Berrange QCryptoTLSSessionHandshakeStatus
qcrypto_tls_session_get_handshake_status(QCryptoTLSSession * session)577d321e1e5SDaniel P. Berrange qcrypto_tls_session_get_handshake_status(QCryptoTLSSession *session)
578d321e1e5SDaniel P. Berrange {
579d321e1e5SDaniel P. Berrange     if (session->handshakeComplete) {
580d321e1e5SDaniel P. Berrange         return QCRYPTO_TLS_HANDSHAKE_COMPLETE;
581d321e1e5SDaniel P. Berrange     } else if (gnutls_record_get_direction(session->handle) == 0) {
582d321e1e5SDaniel P. Berrange         return QCRYPTO_TLS_HANDSHAKE_RECVING;
583d321e1e5SDaniel P. Berrange     } else {
584d321e1e5SDaniel P. Berrange         return QCRYPTO_TLS_HANDSHAKE_SENDING;
585d321e1e5SDaniel P. Berrange     }
586d321e1e5SDaniel P. Berrange }
587d321e1e5SDaniel P. Berrange 
588d321e1e5SDaniel P. Berrange 
589d321e1e5SDaniel P. Berrange int
qcrypto_tls_session_get_key_size(QCryptoTLSSession * session,Error ** errp)590d321e1e5SDaniel P. Berrange qcrypto_tls_session_get_key_size(QCryptoTLSSession *session,
591d321e1e5SDaniel P. Berrange                                  Error **errp)
592d321e1e5SDaniel P. Berrange {
593d321e1e5SDaniel P. Berrange     gnutls_cipher_algorithm_t cipher;
594d321e1e5SDaniel P. Berrange     int ssf;
595d321e1e5SDaniel P. Berrange 
596d321e1e5SDaniel P. Berrange     cipher = gnutls_cipher_get(session->handle);
597d321e1e5SDaniel P. Berrange     ssf = gnutls_cipher_get_key_size(cipher);
598d321e1e5SDaniel P. Berrange     if (!ssf) {
599d321e1e5SDaniel P. Berrange         error_setg(errp, "Cannot get TLS cipher key size");
600d321e1e5SDaniel P. Berrange         return -1;
601d321e1e5SDaniel P. Berrange     }
602d321e1e5SDaniel P. Berrange     return ssf;
603d321e1e5SDaniel P. Berrange }
604d321e1e5SDaniel P. Berrange 
605d321e1e5SDaniel P. Berrange 
606d321e1e5SDaniel P. Berrange char *
qcrypto_tls_session_get_peer_name(QCryptoTLSSession * session)607d321e1e5SDaniel P. Berrange qcrypto_tls_session_get_peer_name(QCryptoTLSSession *session)
608d321e1e5SDaniel P. Berrange {
609d321e1e5SDaniel P. Berrange     if (session->peername) {
610d321e1e5SDaniel P. Berrange         return g_strdup(session->peername);
611d321e1e5SDaniel P. Berrange     }
612d321e1e5SDaniel P. Berrange     return NULL;
613d321e1e5SDaniel P. Berrange }
614d321e1e5SDaniel P. Berrange 
615d321e1e5SDaniel P. Berrange 
616d321e1e5SDaniel P. Berrange #else /* ! CONFIG_GNUTLS */
617d321e1e5SDaniel P. Berrange 
618d321e1e5SDaniel P. Berrange 
619d321e1e5SDaniel P. Berrange QCryptoTLSSession *
qcrypto_tls_session_new(QCryptoTLSCreds * creds G_GNUC_UNUSED,const char * hostname G_GNUC_UNUSED,const char * authzid G_GNUC_UNUSED,QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED,Error ** errp)620d321e1e5SDaniel P. Berrange qcrypto_tls_session_new(QCryptoTLSCreds *creds G_GNUC_UNUSED,
621d321e1e5SDaniel P. Berrange                         const char *hostname G_GNUC_UNUSED,
622b76806d4SDaniel P. Berrange                         const char *authzid G_GNUC_UNUSED,
623d321e1e5SDaniel P. Berrange                         QCryptoTLSCredsEndpoint endpoint G_GNUC_UNUSED,
624d321e1e5SDaniel P. Berrange                         Error **errp)
625d321e1e5SDaniel P. Berrange {
626d321e1e5SDaniel P. Berrange     error_setg(errp, "TLS requires GNUTLS support");
627d321e1e5SDaniel P. Berrange     return NULL;
628d321e1e5SDaniel P. Berrange }
629d321e1e5SDaniel P. Berrange 
630d321e1e5SDaniel P. Berrange 
631d321e1e5SDaniel P. Berrange void
qcrypto_tls_session_free(QCryptoTLSSession * sess G_GNUC_UNUSED)632d321e1e5SDaniel P. Berrange qcrypto_tls_session_free(QCryptoTLSSession *sess G_GNUC_UNUSED)
633d321e1e5SDaniel P. Berrange {
634d321e1e5SDaniel P. Berrange }
635d321e1e5SDaniel P. Berrange 
636d321e1e5SDaniel P. Berrange 
637d321e1e5SDaniel P. Berrange int
qcrypto_tls_session_check_credentials(QCryptoTLSSession * sess G_GNUC_UNUSED,Error ** errp)638d321e1e5SDaniel P. Berrange qcrypto_tls_session_check_credentials(QCryptoTLSSession *sess G_GNUC_UNUSED,
639d321e1e5SDaniel P. Berrange                                       Error **errp)
640d321e1e5SDaniel P. Berrange {
641d321e1e5SDaniel P. Berrange     error_setg(errp, "TLS requires GNUTLS support");
642d321e1e5SDaniel P. Berrange     return -1;
643d321e1e5SDaniel P. Berrange }
644d321e1e5SDaniel P. Berrange 
645d321e1e5SDaniel P. Berrange 
646d321e1e5SDaniel P. Berrange void
qcrypto_tls_session_set_callbacks(QCryptoTLSSession * sess G_GNUC_UNUSED,QCryptoTLSSessionWriteFunc writeFunc G_GNUC_UNUSED,QCryptoTLSSessionReadFunc readFunc G_GNUC_UNUSED,void * opaque G_GNUC_UNUSED)647d321e1e5SDaniel P. Berrange qcrypto_tls_session_set_callbacks(
648d321e1e5SDaniel P. Berrange     QCryptoTLSSession *sess G_GNUC_UNUSED,
649d321e1e5SDaniel P. Berrange     QCryptoTLSSessionWriteFunc writeFunc G_GNUC_UNUSED,
650d321e1e5SDaniel P. Berrange     QCryptoTLSSessionReadFunc readFunc G_GNUC_UNUSED,
651d321e1e5SDaniel P. Berrange     void *opaque G_GNUC_UNUSED)
652d321e1e5SDaniel P. Berrange {
653d321e1e5SDaniel P. Berrange }
654d321e1e5SDaniel P. Berrange 
655d321e1e5SDaniel P. Berrange 
656d321e1e5SDaniel P. Berrange ssize_t
qcrypto_tls_session_write(QCryptoTLSSession * sess,const char * buf,size_t len,Error ** errp)657d321e1e5SDaniel P. Berrange qcrypto_tls_session_write(QCryptoTLSSession *sess,
658d321e1e5SDaniel P. Berrange                           const char *buf,
65957941c9cSDaniel P. Berrangé                           size_t len,
66057941c9cSDaniel P. Berrangé                           Error **errp)
661d321e1e5SDaniel P. Berrange {
66257941c9cSDaniel P. Berrangé     error_setg(errp, "TLS requires GNUTLS support");
663d321e1e5SDaniel P. Berrange     return -1;
664d321e1e5SDaniel P. Berrange }
665d321e1e5SDaniel P. Berrange 
666d321e1e5SDaniel P. Berrange 
667d321e1e5SDaniel P. Berrange ssize_t
qcrypto_tls_session_read(QCryptoTLSSession * sess,char * buf,size_t len,bool gracefulTermination,Error ** errp)668d321e1e5SDaniel P. Berrange qcrypto_tls_session_read(QCryptoTLSSession *sess,
669d321e1e5SDaniel P. Berrange                          char *buf,
67057941c9cSDaniel P. Berrangé                          size_t len,
67157941c9cSDaniel P. Berrangé                          bool gracefulTermination,
67257941c9cSDaniel P. Berrangé                          Error **errp)
673d321e1e5SDaniel P. Berrange {
67457941c9cSDaniel P. Berrangé     error_setg(errp, "TLS requires GNUTLS support");
675d321e1e5SDaniel P. Berrange     return -1;
676d321e1e5SDaniel P. Berrange }
677d321e1e5SDaniel P. Berrange 
678d321e1e5SDaniel P. Berrange 
67933ee0d8eSAntoine Damhet size_t
qcrypto_tls_session_check_pending(QCryptoTLSSession * session)68033ee0d8eSAntoine Damhet qcrypto_tls_session_check_pending(QCryptoTLSSession *session)
68133ee0d8eSAntoine Damhet {
68233ee0d8eSAntoine Damhet     return 0;
68333ee0d8eSAntoine Damhet }
68433ee0d8eSAntoine Damhet 
68533ee0d8eSAntoine Damhet 
686d321e1e5SDaniel P. Berrange int
qcrypto_tls_session_handshake(QCryptoTLSSession * sess,Error ** errp)687d321e1e5SDaniel P. Berrange qcrypto_tls_session_handshake(QCryptoTLSSession *sess,
688d321e1e5SDaniel P. Berrange                               Error **errp)
689d321e1e5SDaniel P. Berrange {
690d321e1e5SDaniel P. Berrange     error_setg(errp, "TLS requires GNUTLS support");
691d321e1e5SDaniel P. Berrange     return -1;
692d321e1e5SDaniel P. Berrange }
693d321e1e5SDaniel P. Berrange 
694d321e1e5SDaniel P. Berrange 
695d321e1e5SDaniel P. Berrange QCryptoTLSSessionHandshakeStatus
qcrypto_tls_session_get_handshake_status(QCryptoTLSSession * sess)696d321e1e5SDaniel P. Berrange qcrypto_tls_session_get_handshake_status(QCryptoTLSSession *sess)
697d321e1e5SDaniel P. Berrange {
698d321e1e5SDaniel P. Berrange     return QCRYPTO_TLS_HANDSHAKE_COMPLETE;
699d321e1e5SDaniel P. Berrange }
700d321e1e5SDaniel P. Berrange 
701d321e1e5SDaniel P. Berrange 
702d321e1e5SDaniel P. Berrange int
qcrypto_tls_session_get_key_size(QCryptoTLSSession * sess,Error ** errp)703d321e1e5SDaniel P. Berrange qcrypto_tls_session_get_key_size(QCryptoTLSSession *sess,
704d321e1e5SDaniel P. Berrange                                  Error **errp)
705d321e1e5SDaniel P. Berrange {
706d321e1e5SDaniel P. Berrange     error_setg(errp, "TLS requires GNUTLS support");
707d321e1e5SDaniel P. Berrange     return -1;
708d321e1e5SDaniel P. Berrange }
709d321e1e5SDaniel P. Berrange 
710d321e1e5SDaniel P. Berrange 
711d321e1e5SDaniel P. Berrange char *
qcrypto_tls_session_get_peer_name(QCryptoTLSSession * sess)712d321e1e5SDaniel P. Berrange qcrypto_tls_session_get_peer_name(QCryptoTLSSession *sess)
713d321e1e5SDaniel P. Berrange {
714d321e1e5SDaniel P. Berrange     return NULL;
715d321e1e5SDaniel P. Berrange }
716d321e1e5SDaniel P. Berrange 
717d321e1e5SDaniel P. Berrange #endif
718