qemu/backends/cryptodev.c
<<
>>
Prefs
   1/*
   2 * QEMU Crypto Device Implementation
   3 *
   4 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
   5 *
   6 * Authors:
   7 *    Gonglei <arei.gonglei@huawei.com>
   8 *
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation; either
  12 * version 2 of the License, or (at your option) any later version.
  13 *
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  21 *
  22 */
  23
  24#include "qemu/osdep.h"
  25#include "sysemu/cryptodev.h"
  26#include "hw/boards.h"
  27#include "qapi/error.h"
  28#include "qapi/visitor.h"
  29#include "qapi-types.h"
  30#include "qapi-visit.h"
  31#include "qemu/config-file.h"
  32#include "qom/object_interfaces.h"
  33#include "hw/virtio/virtio-crypto.h"
  34
  35
  36static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients;
  37
  38
  39CryptoDevBackendClient *
  40cryptodev_backend_new_client(const char *model,
  41                                    const char *name)
  42{
  43    CryptoDevBackendClient *cc;
  44
  45    cc = g_malloc0(sizeof(CryptoDevBackendClient));
  46    cc->model = g_strdup(model);
  47    if (name) {
  48        cc->name = g_strdup(name);
  49    }
  50
  51    QTAILQ_INSERT_TAIL(&crypto_clients, cc, next);
  52
  53    return cc;
  54}
  55
  56void cryptodev_backend_free_client(
  57                  CryptoDevBackendClient *cc)
  58{
  59    QTAILQ_REMOVE(&crypto_clients, cc, next);
  60    g_free(cc->name);
  61    g_free(cc->model);
  62    g_free(cc->info_str);
  63    g_free(cc);
  64}
  65
  66void cryptodev_backend_cleanup(
  67             CryptoDevBackend *backend,
  68             Error **errp)
  69{
  70    CryptoDevBackendClass *bc =
  71                  CRYPTODEV_BACKEND_GET_CLASS(backend);
  72
  73    if (bc->cleanup) {
  74        bc->cleanup(backend, errp);
  75    }
  76}
  77
  78int64_t cryptodev_backend_sym_create_session(
  79           CryptoDevBackend *backend,
  80           CryptoDevBackendSymSessionInfo *sess_info,
  81           uint32_t queue_index, Error **errp)
  82{
  83    CryptoDevBackendClass *bc =
  84                      CRYPTODEV_BACKEND_GET_CLASS(backend);
  85
  86    if (bc->create_session) {
  87        return bc->create_session(backend, sess_info, queue_index, errp);
  88    }
  89
  90    return -1;
  91}
  92
  93int cryptodev_backend_sym_close_session(
  94           CryptoDevBackend *backend,
  95           uint64_t session_id,
  96           uint32_t queue_index, Error **errp)
  97{
  98    CryptoDevBackendClass *bc =
  99                      CRYPTODEV_BACKEND_GET_CLASS(backend);
 100
 101    if (bc->close_session) {
 102        return bc->close_session(backend, session_id, queue_index, errp);
 103    }
 104
 105    return -1;
 106}
 107
 108static int cryptodev_backend_sym_operation(
 109                 CryptoDevBackend *backend,
 110                 CryptoDevBackendSymOpInfo *op_info,
 111                 uint32_t queue_index, Error **errp)
 112{
 113    CryptoDevBackendClass *bc =
 114                      CRYPTODEV_BACKEND_GET_CLASS(backend);
 115
 116    if (bc->do_sym_op) {
 117        return bc->do_sym_op(backend, op_info, queue_index, errp);
 118    }
 119
 120    return -VIRTIO_CRYPTO_ERR;
 121}
 122
 123int cryptodev_backend_crypto_operation(
 124                 CryptoDevBackend *backend,
 125                 void *opaque,
 126                 uint32_t queue_index, Error **errp)
 127{
 128    VirtIOCryptoReq *req = opaque;
 129
 130    if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) {
 131        CryptoDevBackendSymOpInfo *op_info;
 132        op_info = req->u.sym_op_info;
 133
 134        return cryptodev_backend_sym_operation(backend,
 135                         op_info, queue_index, errp);
 136    } else {
 137        error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "",
 138                   req->flags);
 139       return -VIRTIO_CRYPTO_NOTSUPP;
 140    }
 141
 142    return -VIRTIO_CRYPTO_ERR;
 143}
 144
 145static void
 146cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
 147                             void *opaque, Error **errp)
 148{
 149    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 150    uint32_t value = backend->conf.peers.queues;
 151
 152    visit_type_uint32(v, name, &value, errp);
 153}
 154
 155static void
 156cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
 157                             void *opaque, Error **errp)
 158{
 159    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 160    Error *local_err = NULL;
 161    uint32_t value;
 162
 163    visit_type_uint32(v, name, &value, &local_err);
 164    if (local_err) {
 165        goto out;
 166    }
 167    if (!value) {
 168        error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
 169                   PRIu32 "'", object_get_typename(obj), name, value);
 170        goto out;
 171    }
 172    backend->conf.peers.queues = value;
 173out:
 174    error_propagate(errp, local_err);
 175}
 176
 177static void
 178cryptodev_backend_complete(UserCreatable *uc, Error **errp)
 179{
 180    CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
 181    CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
 182    Error *local_err = NULL;
 183
 184    if (bc->init) {
 185        bc->init(backend, &local_err);
 186        if (local_err) {
 187            goto out;
 188        }
 189    }
 190
 191    return;
 192
 193out:
 194    error_propagate(errp, local_err);
 195}
 196
 197void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used)
 198{
 199    backend->is_used = used;
 200}
 201
 202bool cryptodev_backend_is_used(CryptoDevBackend *backend)
 203{
 204    return backend->is_used;
 205}
 206
 207void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready)
 208{
 209    backend->ready = ready;
 210}
 211
 212bool cryptodev_backend_is_ready(CryptoDevBackend *backend)
 213{
 214    return backend->ready;
 215}
 216
 217static bool
 218cryptodev_backend_can_be_deleted(UserCreatable *uc, Error **errp)
 219{
 220    return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc));
 221}
 222
 223static void cryptodev_backend_instance_init(Object *obj)
 224{
 225    object_property_add(obj, "queues", "uint32",
 226                          cryptodev_backend_get_queues,
 227                          cryptodev_backend_set_queues,
 228                          NULL, NULL, NULL);
 229    /* Initialize devices' queues property to 1 */
 230    object_property_set_int(obj, 1, "queues", NULL);
 231}
 232
 233static void cryptodev_backend_finalize(Object *obj)
 234{
 235    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 236
 237    cryptodev_backend_cleanup(backend, NULL);
 238}
 239
 240static void
 241cryptodev_backend_class_init(ObjectClass *oc, void *data)
 242{
 243    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 244
 245    ucc->complete = cryptodev_backend_complete;
 246    ucc->can_be_deleted = cryptodev_backend_can_be_deleted;
 247
 248    QTAILQ_INIT(&crypto_clients);
 249}
 250
 251static const TypeInfo cryptodev_backend_info = {
 252    .name = TYPE_CRYPTODEV_BACKEND,
 253    .parent = TYPE_OBJECT,
 254    .instance_size = sizeof(CryptoDevBackend),
 255    .instance_init = cryptodev_backend_instance_init,
 256    .instance_finalize = cryptodev_backend_finalize,
 257    .class_size = sizeof(CryptoDevBackendClass),
 258    .class_init = cryptodev_backend_class_init,
 259    .interfaces = (InterfaceInfo[]) {
 260        { TYPE_USER_CREATABLE },
 261        { }
 262    }
 263};
 264
 265static void
 266cryptodev_backend_register_types(void)
 267{
 268    type_register_static(&cryptodev_backend_info);
 269}
 270
 271type_init(cryptodev_backend_register_types);
 272