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    backend->ready = false;
  78}
  79
  80int64_t cryptodev_backend_sym_create_session(
  81           CryptoDevBackend *backend,
  82           CryptoDevBackendSymSessionInfo *sess_info,
  83           uint32_t queue_index, Error **errp)
  84{
  85    CryptoDevBackendClass *bc =
  86                      CRYPTODEV_BACKEND_GET_CLASS(backend);
  87
  88    if (bc->create_session) {
  89        return bc->create_session(backend, sess_info, queue_index, errp);
  90    }
  91
  92    return -1;
  93}
  94
  95int cryptodev_backend_sym_close_session(
  96           CryptoDevBackend *backend,
  97           uint64_t session_id,
  98           uint32_t queue_index, Error **errp)
  99{
 100    CryptoDevBackendClass *bc =
 101                      CRYPTODEV_BACKEND_GET_CLASS(backend);
 102
 103    if (bc->close_session) {
 104        return bc->close_session(backend, session_id, queue_index, errp);
 105    }
 106
 107    return -1;
 108}
 109
 110static int cryptodev_backend_sym_operation(
 111                 CryptoDevBackend *backend,
 112                 CryptoDevBackendSymOpInfo *op_info,
 113                 uint32_t queue_index, Error **errp)
 114{
 115    CryptoDevBackendClass *bc =
 116                      CRYPTODEV_BACKEND_GET_CLASS(backend);
 117
 118    if (bc->do_sym_op) {
 119        return bc->do_sym_op(backend, op_info, queue_index, errp);
 120    }
 121
 122    return -VIRTIO_CRYPTO_ERR;
 123}
 124
 125int cryptodev_backend_crypto_operation(
 126                 CryptoDevBackend *backend,
 127                 void *opaque,
 128                 uint32_t queue_index, Error **errp)
 129{
 130    VirtIOCryptoReq *req = opaque;
 131
 132    if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) {
 133        CryptoDevBackendSymOpInfo *op_info;
 134        op_info = req->u.sym_op_info;
 135
 136        return cryptodev_backend_sym_operation(backend,
 137                         op_info, queue_index, errp);
 138    } else {
 139        error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "",
 140                   req->flags);
 141       return -VIRTIO_CRYPTO_NOTSUPP;
 142    }
 143
 144    return -VIRTIO_CRYPTO_ERR;
 145}
 146
 147static void
 148cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
 149                             void *opaque, Error **errp)
 150{
 151    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 152    uint32_t value = backend->conf.peers.queues;
 153
 154    visit_type_uint32(v, name, &value, errp);
 155}
 156
 157static void
 158cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
 159                             void *opaque, Error **errp)
 160{
 161    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 162    Error *local_err = NULL;
 163    uint32_t value;
 164
 165    visit_type_uint32(v, name, &value, &local_err);
 166    if (local_err) {
 167        goto out;
 168    }
 169    if (!value) {
 170        error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
 171                   PRIu32 "'", object_get_typename(obj), name, value);
 172        goto out;
 173    }
 174    backend->conf.peers.queues = value;
 175out:
 176    error_propagate(errp, local_err);
 177}
 178
 179static void
 180cryptodev_backend_complete(UserCreatable *uc, Error **errp)
 181{
 182    CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
 183    CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
 184    Error *local_err = NULL;
 185
 186    if (bc->init) {
 187        bc->init(backend, &local_err);
 188        if (local_err) {
 189            goto out;
 190        }
 191    }
 192    backend->ready = true;
 193    return;
 194
 195out:
 196    backend->ready = false;
 197    error_propagate(errp, local_err);
 198}
 199
 200static void cryptodev_backend_instance_init(Object *obj)
 201{
 202    object_property_add(obj, "queues", "int",
 203                          cryptodev_backend_get_queues,
 204                          cryptodev_backend_set_queues,
 205                          NULL, NULL, NULL);
 206    /* Initialize devices' queues property to 1 */
 207    object_property_set_int(obj, 1, "queues", NULL);
 208}
 209
 210static void cryptodev_backend_finalize(Object *obj)
 211{
 212
 213}
 214
 215static void
 216cryptodev_backend_class_init(ObjectClass *oc, void *data)
 217{
 218    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 219
 220    ucc->complete = cryptodev_backend_complete;
 221
 222    QTAILQ_INIT(&crypto_clients);
 223}
 224
 225static const TypeInfo cryptodev_backend_info = {
 226    .name = TYPE_CRYPTODEV_BACKEND,
 227    .parent = TYPE_OBJECT,
 228    .instance_size = sizeof(CryptoDevBackend),
 229    .instance_init = cryptodev_backend_instance_init,
 230    .instance_finalize = cryptodev_backend_finalize,
 231    .class_size = sizeof(CryptoDevBackendClass),
 232    .class_init = cryptodev_backend_class_init,
 233    .interfaces = (InterfaceInfo[]) {
 234        { TYPE_USER_CREATABLE },
 235        { }
 236    }
 237};
 238
 239static void
 240cryptodev_backend_register_types(void)
 241{
 242    type_register_static(&cryptodev_backend_info);
 243}
 244
 245type_init(cryptodev_backend_register_types);
 246