xref: /openbmc/qemu/io/channel-tls.c (revision 51e47cf8)
1 /*
2  * QEMU I/O channels TLS driver
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "qemu/module.h"
24 #include "io/channel-tls.h"
25 #include "trace.h"
26 #include "qemu/atomic.h"
27 
28 
29 static ssize_t qio_channel_tls_write_handler(const char *buf,
30                                              size_t len,
31                                              void *opaque)
32 {
33     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
34     ssize_t ret;
35 
36     ret = qio_channel_write(tioc->master, buf, len, NULL);
37     if (ret == QIO_CHANNEL_ERR_BLOCK) {
38         errno = EAGAIN;
39         return -1;
40     } else if (ret < 0) {
41         errno = EIO;
42         return -1;
43     }
44     return ret;
45 }
46 
47 static ssize_t qio_channel_tls_read_handler(char *buf,
48                                             size_t len,
49                                             void *opaque)
50 {
51     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
52     ssize_t ret;
53 
54     ret = qio_channel_read(tioc->master, buf, len, NULL);
55     if (ret == QIO_CHANNEL_ERR_BLOCK) {
56         errno = EAGAIN;
57         return -1;
58     } else if (ret < 0) {
59         errno = EIO;
60         return -1;
61     }
62     return ret;
63 }
64 
65 
66 QIOChannelTLS *
67 qio_channel_tls_new_server(QIOChannel *master,
68                            QCryptoTLSCreds *creds,
69                            const char *aclname,
70                            Error **errp)
71 {
72     QIOChannelTLS *ioc;
73 
74     ioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS));
75 
76     ioc->master = master;
77     if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) {
78         qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SHUTDOWN);
79     }
80     object_ref(OBJECT(master));
81 
82     ioc->session = qcrypto_tls_session_new(
83         creds,
84         NULL,
85         aclname,
86         QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
87         errp);
88     if (!ioc->session) {
89         goto error;
90     }
91 
92     qcrypto_tls_session_set_callbacks(
93         ioc->session,
94         qio_channel_tls_write_handler,
95         qio_channel_tls_read_handler,
96         ioc);
97 
98     trace_qio_channel_tls_new_server(ioc, master, creds, aclname);
99     return ioc;
100 
101  error:
102     object_unref(OBJECT(ioc));
103     return NULL;
104 }
105 
106 QIOChannelTLS *
107 qio_channel_tls_new_client(QIOChannel *master,
108                            QCryptoTLSCreds *creds,
109                            const char *hostname,
110                            Error **errp)
111 {
112     QIOChannelTLS *tioc;
113     QIOChannel *ioc;
114 
115     tioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS));
116     ioc = QIO_CHANNEL(tioc);
117 
118     tioc->master = master;
119     if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) {
120         qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
121     }
122     object_ref(OBJECT(master));
123 
124     tioc->session = qcrypto_tls_session_new(
125         creds,
126         hostname,
127         NULL,
128         QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
129         errp);
130     if (!tioc->session) {
131         goto error;
132     }
133 
134     qcrypto_tls_session_set_callbacks(
135         tioc->session,
136         qio_channel_tls_write_handler,
137         qio_channel_tls_read_handler,
138         tioc);
139 
140     trace_qio_channel_tls_new_client(tioc, master, creds, hostname);
141     return tioc;
142 
143  error:
144     object_unref(OBJECT(tioc));
145     return NULL;
146 }
147 
148 struct QIOChannelTLSData {
149     QIOTask *task;
150     GMainContext *context;
151 };
152 typedef struct QIOChannelTLSData QIOChannelTLSData;
153 
154 static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
155                                              GIOCondition condition,
156                                              gpointer user_data);
157 
158 static void qio_channel_tls_handshake_task(QIOChannelTLS *ioc,
159                                            QIOTask *task,
160                                            GMainContext *context)
161 {
162     Error *err = NULL;
163     QCryptoTLSSessionHandshakeStatus status;
164 
165     if (qcrypto_tls_session_handshake(ioc->session, &err) < 0) {
166         trace_qio_channel_tls_handshake_fail(ioc);
167         qio_task_set_error(task, err);
168         qio_task_complete(task);
169         return;
170     }
171 
172     status = qcrypto_tls_session_get_handshake_status(ioc->session);
173     if (status == QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
174         trace_qio_channel_tls_handshake_complete(ioc);
175         if (qcrypto_tls_session_check_credentials(ioc->session,
176                                                   &err) < 0) {
177             trace_qio_channel_tls_credentials_deny(ioc);
178             qio_task_set_error(task, err);
179         } else {
180             trace_qio_channel_tls_credentials_allow(ioc);
181         }
182         qio_task_complete(task);
183     } else {
184         GIOCondition condition;
185         QIOChannelTLSData *data = g_new0(typeof(*data), 1);
186 
187         data->task = task;
188         data->context = context;
189 
190         if (context) {
191             g_main_context_ref(context);
192         }
193 
194         if (status == QCRYPTO_TLS_HANDSHAKE_SENDING) {
195             condition = G_IO_OUT;
196         } else {
197             condition = G_IO_IN;
198         }
199 
200         trace_qio_channel_tls_handshake_pending(ioc, status);
201         qio_channel_add_watch_full(ioc->master,
202                                    condition,
203                                    qio_channel_tls_handshake_io,
204                                    data,
205                                    NULL,
206                                    context);
207     }
208 }
209 
210 
211 static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
212                                              GIOCondition condition,
213                                              gpointer user_data)
214 {
215     QIOChannelTLSData *data = user_data;
216     QIOTask *task = data->task;
217     GMainContext *context = data->context;
218     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(
219         qio_task_get_source(task));
220 
221     g_free(data);
222     qio_channel_tls_handshake_task(tioc, task, context);
223 
224     if (context) {
225         g_main_context_unref(context);
226     }
227 
228     return FALSE;
229 }
230 
231 void qio_channel_tls_handshake(QIOChannelTLS *ioc,
232                                QIOTaskFunc func,
233                                gpointer opaque,
234                                GDestroyNotify destroy,
235                                GMainContext *context)
236 {
237     QIOTask *task;
238 
239     task = qio_task_new(OBJECT(ioc),
240                         func, opaque, destroy);
241 
242     trace_qio_channel_tls_handshake_start(ioc);
243     qio_channel_tls_handshake_task(ioc, task, context);
244 }
245 
246 
247 static void qio_channel_tls_init(Object *obj G_GNUC_UNUSED)
248 {
249 }
250 
251 
252 static void qio_channel_tls_finalize(Object *obj)
253 {
254     QIOChannelTLS *ioc = QIO_CHANNEL_TLS(obj);
255 
256     object_unref(OBJECT(ioc->master));
257     qcrypto_tls_session_free(ioc->session);
258 }
259 
260 
261 static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
262                                      const struct iovec *iov,
263                                      size_t niov,
264                                      int **fds,
265                                      size_t *nfds,
266                                      int flags,
267                                      Error **errp)
268 {
269     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
270     size_t i;
271     ssize_t got = 0;
272 
273     for (i = 0 ; i < niov ; i++) {
274         ssize_t ret = qcrypto_tls_session_read(tioc->session,
275                                                iov[i].iov_base,
276                                                iov[i].iov_len);
277         if (ret < 0) {
278             if (errno == EAGAIN) {
279                 if (got) {
280                     return got;
281                 } else {
282                     return QIO_CHANNEL_ERR_BLOCK;
283                 }
284             } else if (errno == ECONNABORTED &&
285                        (qatomic_load_acquire(&tioc->shutdown) &
286                         QIO_CHANNEL_SHUTDOWN_READ)) {
287                 return 0;
288             }
289 
290             error_setg_errno(errp, errno,
291                              "Cannot read from TLS channel");
292             return -1;
293         }
294         got += ret;
295         if (ret < iov[i].iov_len) {
296             break;
297         }
298     }
299     return got;
300 }
301 
302 
303 static ssize_t qio_channel_tls_writev(QIOChannel *ioc,
304                                       const struct iovec *iov,
305                                       size_t niov,
306                                       int *fds,
307                                       size_t nfds,
308                                       int flags,
309                                       Error **errp)
310 {
311     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
312     size_t i;
313     ssize_t done = 0;
314 
315     for (i = 0 ; i < niov ; i++) {
316         ssize_t ret = qcrypto_tls_session_write(tioc->session,
317                                                 iov[i].iov_base,
318                                                 iov[i].iov_len);
319         if (ret <= 0) {
320             if (errno == EAGAIN) {
321                 if (done) {
322                     return done;
323                 } else {
324                     return QIO_CHANNEL_ERR_BLOCK;
325                 }
326             }
327 
328             error_setg_errno(errp, errno,
329                              "Cannot write to TLS channel");
330             return -1;
331         }
332         done += ret;
333         if (ret < iov[i].iov_len) {
334             break;
335         }
336     }
337     return done;
338 }
339 
340 static int qio_channel_tls_set_blocking(QIOChannel *ioc,
341                                         bool enabled,
342                                         Error **errp)
343 {
344     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
345 
346     return qio_channel_set_blocking(tioc->master, enabled, errp);
347 }
348 
349 static void qio_channel_tls_set_delay(QIOChannel *ioc,
350                                       bool enabled)
351 {
352     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
353 
354     qio_channel_set_delay(tioc->master, enabled);
355 }
356 
357 static void qio_channel_tls_set_cork(QIOChannel *ioc,
358                                      bool enabled)
359 {
360     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
361 
362     qio_channel_set_cork(tioc->master, enabled);
363 }
364 
365 static int qio_channel_tls_shutdown(QIOChannel *ioc,
366                                     QIOChannelShutdown how,
367                                     Error **errp)
368 {
369     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
370 
371     qatomic_or(&tioc->shutdown, how);
372 
373     return qio_channel_shutdown(tioc->master, how, errp);
374 }
375 
376 static int qio_channel_tls_close(QIOChannel *ioc,
377                                  Error **errp)
378 {
379     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
380 
381     return qio_channel_close(tioc->master, errp);
382 }
383 
384 static void qio_channel_tls_set_aio_fd_handler(QIOChannel *ioc,
385                                                AioContext *ctx,
386                                                IOHandler *io_read,
387                                                IOHandler *io_write,
388                                                void *opaque)
389 {
390     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
391 
392     qio_channel_set_aio_fd_handler(tioc->master, ctx, io_read, io_write, opaque);
393 }
394 
395 typedef struct QIOChannelTLSSource QIOChannelTLSSource;
396 struct QIOChannelTLSSource {
397     GSource parent;
398     QIOChannelTLS *tioc;
399 };
400 
401 static gboolean
402 qio_channel_tls_source_check(GSource *source)
403 {
404     QIOChannelTLSSource *tsource = (QIOChannelTLSSource *)source;
405 
406     return qcrypto_tls_session_check_pending(tsource->tioc->session) > 0;
407 }
408 
409 static gboolean
410 qio_channel_tls_source_prepare(GSource *source, gint *timeout)
411 {
412     *timeout = -1;
413     return qio_channel_tls_source_check(source);
414 }
415 
416 static gboolean
417 qio_channel_tls_source_dispatch(GSource *source, GSourceFunc callback,
418                                 gpointer user_data)
419 {
420     return G_SOURCE_CONTINUE;
421 }
422 
423 static void
424 qio_channel_tls_source_finalize(GSource *source)
425 {
426     QIOChannelTLSSource *tsource = (QIOChannelTLSSource *)source;
427 
428     object_unref(OBJECT(tsource->tioc));
429 }
430 
431 static GSourceFuncs qio_channel_tls_source_funcs = {
432     qio_channel_tls_source_prepare,
433     qio_channel_tls_source_check,
434     qio_channel_tls_source_dispatch,
435     qio_channel_tls_source_finalize
436 };
437 
438 static void
439 qio_channel_tls_read_watch(QIOChannelTLS *tioc, GSource *source)
440 {
441     GSource *child;
442     QIOChannelTLSSource *tlssource;
443 
444     child = g_source_new(&qio_channel_tls_source_funcs,
445                           sizeof(QIOChannelTLSSource));
446     tlssource = (QIOChannelTLSSource *)child;
447 
448     tlssource->tioc = tioc;
449     object_ref(OBJECT(tioc));
450 
451     g_source_add_child_source(source, child);
452     g_source_unref(child);
453 }
454 
455 static GSource *qio_channel_tls_create_watch(QIOChannel *ioc,
456                                              GIOCondition condition)
457 {
458     QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
459     GSource *source = qio_channel_create_watch(tioc->master, condition);
460 
461     if (condition & G_IO_IN) {
462         qio_channel_tls_read_watch(tioc, source);
463     }
464 
465     return source;
466 }
467 
468 QCryptoTLSSession *
469 qio_channel_tls_get_session(QIOChannelTLS *ioc)
470 {
471     return ioc->session;
472 }
473 
474 static void qio_channel_tls_class_init(ObjectClass *klass,
475                                        void *class_data G_GNUC_UNUSED)
476 {
477     QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
478 
479     ioc_klass->io_writev = qio_channel_tls_writev;
480     ioc_klass->io_readv = qio_channel_tls_readv;
481     ioc_klass->io_set_blocking = qio_channel_tls_set_blocking;
482     ioc_klass->io_set_delay = qio_channel_tls_set_delay;
483     ioc_klass->io_set_cork = qio_channel_tls_set_cork;
484     ioc_klass->io_close = qio_channel_tls_close;
485     ioc_klass->io_shutdown = qio_channel_tls_shutdown;
486     ioc_klass->io_create_watch = qio_channel_tls_create_watch;
487     ioc_klass->io_set_aio_fd_handler = qio_channel_tls_set_aio_fd_handler;
488 }
489 
490 static const TypeInfo qio_channel_tls_info = {
491     .parent = TYPE_QIO_CHANNEL,
492     .name = TYPE_QIO_CHANNEL_TLS,
493     .instance_size = sizeof(QIOChannelTLS),
494     .instance_init = qio_channel_tls_init,
495     .instance_finalize = qio_channel_tls_finalize,
496     .class_init = qio_channel_tls_class_init,
497 };
498 
499 static void qio_channel_tls_register_types(void)
500 {
501     type_register_static(&qio_channel_tls_info);
502 }
503 
504 type_init(qio_channel_tls_register_types);
505