cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

tls.c (5219B)


      1/*
      2 * QEMU migration TLS support
      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 "channel.h"
     23#include "migration.h"
     24#include "tls.h"
     25#include "crypto/tlscreds.h"
     26#include "qemu/error-report.h"
     27#include "qapi/error.h"
     28#include "trace.h"
     29
     30static QCryptoTLSCreds *
     31migration_tls_get_creds(MigrationState *s,
     32                        QCryptoTLSCredsEndpoint endpoint,
     33                        Error **errp)
     34{
     35    Object *creds;
     36    QCryptoTLSCreds *ret;
     37
     38    creds = object_resolve_path_component(
     39        object_get_objects_root(), s->parameters.tls_creds);
     40    if (!creds) {
     41        error_setg(errp, "No TLS credentials with id '%s'",
     42                   s->parameters.tls_creds);
     43        return NULL;
     44    }
     45    ret = (QCryptoTLSCreds *)object_dynamic_cast(
     46        creds, TYPE_QCRYPTO_TLS_CREDS);
     47    if (!ret) {
     48        error_setg(errp, "Object with id '%s' is not TLS credentials",
     49                   s->parameters.tls_creds);
     50        return NULL;
     51    }
     52    if (!qcrypto_tls_creds_check_endpoint(ret, endpoint, errp)) {
     53        return NULL;
     54    }
     55
     56    return ret;
     57}
     58
     59
     60static void migration_tls_incoming_handshake(QIOTask *task,
     61                                             gpointer opaque)
     62{
     63    QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
     64    Error *err = NULL;
     65
     66    if (qio_task_propagate_error(task, &err)) {
     67        trace_migration_tls_incoming_handshake_error(error_get_pretty(err));
     68        error_report_err(err);
     69    } else {
     70        trace_migration_tls_incoming_handshake_complete();
     71        migration_channel_process_incoming(ioc);
     72    }
     73    object_unref(OBJECT(ioc));
     74}
     75
     76void migration_tls_channel_process_incoming(MigrationState *s,
     77                                            QIOChannel *ioc,
     78                                            Error **errp)
     79{
     80    QCryptoTLSCreds *creds;
     81    QIOChannelTLS *tioc;
     82
     83    creds = migration_tls_get_creds(
     84        s, QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, errp);
     85    if (!creds) {
     86        return;
     87    }
     88
     89    tioc = qio_channel_tls_new_server(
     90        ioc, creds,
     91        s->parameters.tls_authz,
     92        errp);
     93    if (!tioc) {
     94        return;
     95    }
     96
     97    trace_migration_tls_incoming_handshake_start();
     98    qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-incoming");
     99    qio_channel_tls_handshake(tioc,
    100                              migration_tls_incoming_handshake,
    101                              NULL,
    102                              NULL,
    103                              NULL);
    104}
    105
    106
    107static void migration_tls_outgoing_handshake(QIOTask *task,
    108                                             gpointer opaque)
    109{
    110    MigrationState *s = opaque;
    111    QIOChannel *ioc = QIO_CHANNEL(qio_task_get_source(task));
    112    Error *err = NULL;
    113
    114    if (qio_task_propagate_error(task, &err)) {
    115        trace_migration_tls_outgoing_handshake_error(error_get_pretty(err));
    116    } else {
    117        trace_migration_tls_outgoing_handshake_complete();
    118    }
    119    migration_channel_connect(s, ioc, NULL, err);
    120    object_unref(OBJECT(ioc));
    121}
    122
    123QIOChannelTLS *migration_tls_client_create(MigrationState *s,
    124                                           QIOChannel *ioc,
    125                                           const char *hostname,
    126                                           Error **errp)
    127{
    128    QCryptoTLSCreds *creds;
    129    QIOChannelTLS *tioc;
    130
    131    creds = migration_tls_get_creds(
    132        s, QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT, errp);
    133    if (!creds) {
    134        return NULL;
    135    }
    136
    137    if (s->parameters.tls_hostname && *s->parameters.tls_hostname) {
    138        hostname = s->parameters.tls_hostname;
    139    }
    140    if (!hostname) {
    141        error_setg(errp, "No hostname available for TLS");
    142        return NULL;
    143    }
    144
    145    tioc = qio_channel_tls_new_client(
    146        ioc, creds, hostname, errp);
    147
    148    return tioc;
    149}
    150
    151void migration_tls_channel_connect(MigrationState *s,
    152                                   QIOChannel *ioc,
    153                                   const char *hostname,
    154                                   Error **errp)
    155{
    156    QIOChannelTLS *tioc;
    157
    158    tioc = migration_tls_client_create(s, ioc, hostname, errp);
    159    if (!tioc) {
    160        return;
    161    }
    162
    163    /* Save hostname into MigrationState for handshake */
    164    s->hostname = g_strdup(hostname);
    165    trace_migration_tls_outgoing_handshake_start(hostname);
    166    qio_channel_set_name(QIO_CHANNEL(tioc), "migration-tls-outgoing");
    167    qio_channel_tls_handshake(tioc,
    168                              migration_tls_outgoing_handshake,
    169                              s,
    170                              NULL,
    171                              NULL);
    172}