2 * QEMU I/O channels TLS driver
4 * Copyright (c) 2015 Red Hat, Inc.
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 of the License, or (at your option) any later version.
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.
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/>.
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "io/channel-tls.h"
27 static ssize_t qio_channel_tls_write_handler(const char *buf,
31 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
34 ret = qio_channel_write(tioc->master, buf, len, NULL);
35 if (ret == QIO_CHANNEL_ERR_BLOCK) {
45 static ssize_t qio_channel_tls_read_handler(char *buf,
49 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(opaque);
52 ret = qio_channel_read(tioc->master, buf, len, NULL);
53 if (ret == QIO_CHANNEL_ERR_BLOCK) {
65 qio_channel_tls_new_server(QIOChannel *master,
66 QCryptoTLSCreds *creds,
72 ioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS));
75 object_ref(OBJECT(master));
77 ioc->session = qcrypto_tls_session_new(
81 QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
87 qcrypto_tls_session_set_callbacks(
89 qio_channel_tls_write_handler,
90 qio_channel_tls_read_handler,
93 trace_qio_channel_tls_new_server(ioc, master, creds, aclname);
97 object_unref(OBJECT(ioc));
102 qio_channel_tls_new_client(QIOChannel *master,
103 QCryptoTLSCreds *creds,
104 const char *hostname,
110 tioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS));
111 ioc = QIO_CHANNEL(tioc);
113 tioc->master = master;
114 if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) {
115 qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
117 object_ref(OBJECT(master));
119 tioc->session = qcrypto_tls_session_new(
123 QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
125 if (!tioc->session) {
129 qcrypto_tls_session_set_callbacks(
131 qio_channel_tls_write_handler,
132 qio_channel_tls_read_handler,
135 trace_qio_channel_tls_new_client(tioc, master, creds, hostname);
139 object_unref(OBJECT(tioc));
143 struct QIOChannelTLSData {
145 GMainContext *context;
147 typedef struct QIOChannelTLSData QIOChannelTLSData;
149 static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
150 GIOCondition condition,
153 static void qio_channel_tls_handshake_task(QIOChannelTLS *ioc,
155 GMainContext *context)
158 QCryptoTLSSessionHandshakeStatus status;
160 if (qcrypto_tls_session_handshake(ioc->session, &err) < 0) {
161 trace_qio_channel_tls_handshake_fail(ioc);
162 qio_task_set_error(task, err);
163 qio_task_complete(task);
167 status = qcrypto_tls_session_get_handshake_status(ioc->session);
168 if (status == QCRYPTO_TLS_HANDSHAKE_COMPLETE) {
169 trace_qio_channel_tls_handshake_complete(ioc);
170 if (qcrypto_tls_session_check_credentials(ioc->session,
172 trace_qio_channel_tls_credentials_deny(ioc);
173 qio_task_set_error(task, err);
175 trace_qio_channel_tls_credentials_allow(ioc);
177 qio_task_complete(task);
179 GIOCondition condition;
180 QIOChannelTLSData *data = g_new0(typeof(*data), 1);
183 data->context = context;
186 g_main_context_ref(context);
189 if (status == QCRYPTO_TLS_HANDSHAKE_SENDING) {
190 condition = G_IO_OUT;
195 trace_qio_channel_tls_handshake_pending(ioc, status);
196 qio_channel_add_watch_full(ioc->master,
198 qio_channel_tls_handshake_io,
206 static gboolean qio_channel_tls_handshake_io(QIOChannel *ioc,
207 GIOCondition condition,
210 QIOChannelTLSData *data = user_data;
211 QIOTask *task = data->task;
212 GMainContext *context = data->context;
213 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(
214 qio_task_get_source(task));
217 qio_channel_tls_handshake_task(tioc, task, context);
220 g_main_context_unref(context);
226 void qio_channel_tls_handshake(QIOChannelTLS *ioc,
229 GDestroyNotify destroy,
230 GMainContext *context)
234 task = qio_task_new(OBJECT(ioc),
235 func, opaque, destroy);
237 trace_qio_channel_tls_handshake_start(ioc);
238 qio_channel_tls_handshake_task(ioc, task, context);
242 static void qio_channel_tls_init(Object *obj G_GNUC_UNUSED)
247 static void qio_channel_tls_finalize(Object *obj)
249 QIOChannelTLS *ioc = QIO_CHANNEL_TLS(obj);
251 object_unref(OBJECT(ioc->master));
252 qcrypto_tls_session_free(ioc->session);
256 static ssize_t qio_channel_tls_readv(QIOChannel *ioc,
257 const struct iovec *iov,
263 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
267 for (i = 0 ; i < niov ; i++) {
268 ssize_t ret = qcrypto_tls_session_read(tioc->session,
272 if (errno == EAGAIN) {
276 return QIO_CHANNEL_ERR_BLOCK;
280 error_setg_errno(errp, errno,
281 "Cannot read from TLS channel");
285 if (ret < iov[i].iov_len) {
293 static ssize_t qio_channel_tls_writev(QIOChannel *ioc,
294 const struct iovec *iov,
300 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
304 for (i = 0 ; i < niov ; i++) {
305 ssize_t ret = qcrypto_tls_session_write(tioc->session,
309 if (errno == EAGAIN) {
313 return QIO_CHANNEL_ERR_BLOCK;
317 error_setg_errno(errp, errno,
318 "Cannot write to TLS channel");
322 if (ret < iov[i].iov_len) {
329 static int qio_channel_tls_set_blocking(QIOChannel *ioc,
333 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
335 return qio_channel_set_blocking(tioc->master, enabled, errp);
338 static void qio_channel_tls_set_delay(QIOChannel *ioc,
341 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
343 qio_channel_set_delay(tioc->master, enabled);
346 static void qio_channel_tls_set_cork(QIOChannel *ioc,
349 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
351 qio_channel_set_cork(tioc->master, enabled);
354 static int qio_channel_tls_shutdown(QIOChannel *ioc,
355 QIOChannelShutdown how,
358 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
360 return qio_channel_shutdown(tioc->master, how, errp);
363 static int qio_channel_tls_close(QIOChannel *ioc,
366 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
368 return qio_channel_close(tioc->master, errp);
371 static void qio_channel_tls_set_aio_fd_handler(QIOChannel *ioc,
377 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
379 qio_channel_set_aio_fd_handler(tioc->master, ctx, io_read, io_write, opaque);
382 static GSource *qio_channel_tls_create_watch(QIOChannel *ioc,
383 GIOCondition condition)
385 QIOChannelTLS *tioc = QIO_CHANNEL_TLS(ioc);
387 return qio_channel_create_watch(tioc->master, condition);
391 qio_channel_tls_get_session(QIOChannelTLS *ioc)
396 static void qio_channel_tls_class_init(ObjectClass *klass,
397 void *class_data G_GNUC_UNUSED)
399 QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
401 ioc_klass->io_writev = qio_channel_tls_writev;
402 ioc_klass->io_readv = qio_channel_tls_readv;
403 ioc_klass->io_set_blocking = qio_channel_tls_set_blocking;
404 ioc_klass->io_set_delay = qio_channel_tls_set_delay;
405 ioc_klass->io_set_cork = qio_channel_tls_set_cork;
406 ioc_klass->io_close = qio_channel_tls_close;
407 ioc_klass->io_shutdown = qio_channel_tls_shutdown;
408 ioc_klass->io_create_watch = qio_channel_tls_create_watch;
409 ioc_klass->io_set_aio_fd_handler = qio_channel_tls_set_aio_fd_handler;
412 static const TypeInfo qio_channel_tls_info = {
413 .parent = TYPE_QIO_CHANNEL,
414 .name = TYPE_QIO_CHANNEL_TLS,
415 .instance_size = sizeof(QIOChannelTLS),
416 .instance_init = qio_channel_tls_init,
417 .instance_finalize = qio_channel_tls_finalize,
418 .class_init = qio_channel_tls_class_init,
421 static void qio_channel_tls_register_types(void)
423 type_register_static(&qio_channel_tls_info);
426 type_init(qio_channel_tls_register_types);