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 "qemu/config-file.h"
  30#include "qom/object_interfaces.h"
  31#include "hw/virtio/virtio-crypto.h"
  32
  33
  34static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients;
  35
  36
  37CryptoDevBackendClient *
  38cryptodev_backend_new_client(const char *model,
  39                                    const char *name)
  40{
  41    CryptoDevBackendClient *cc;
  42
  43    cc = g_malloc0(sizeof(CryptoDevBackendClient));
  44    cc->model = g_strdup(model);
  45    if (name) {
  46        cc->name = g_strdup(name);
  47    }
  48
  49    QTAILQ_INSERT_TAIL(&crypto_clients, cc, next);
  50
  51    return cc;
  52}
  53
  54void cryptodev_backend_free_client(
  55                  CryptoDevBackendClient *cc)
  56{
  57    QTAILQ_REMOVE(&crypto_clients, cc, next);
  58    g_free(cc->name);
  59    g_free(cc->model);
  60    g_free(cc->info_str);
  61    g_free(cc);
  62}
  63
  64void cryptodev_backend_cleanup(
  65             CryptoDevBackend *backend,
  66             Error **errp)
  67{
  68    CryptoDevBackendClass *bc =
  69                  CRYPTODEV_BACKEND_GET_CLASS(backend);
  70
  71    if (bc->cleanup) {
  72        bc->cleanup(backend, errp);
  73    }
  74}
  75
  76int64_t cryptodev_backend_sym_create_session(
  77           CryptoDevBackend *backend,
  78           CryptoDevBackendSymSessionInfo *sess_info,
  79           uint32_t queue_index, Error **errp)
  80{
  81    CryptoDevBackendClass *bc =
  82                      CRYPTODEV_BACKEND_GET_CLASS(backend);
  83
  84    if (bc->create_session) {
  85        return bc->create_session(backend, sess_info, queue_index, errp);
  86    }
  87
  88    return -1;
  89}
  90
  91int cryptodev_backend_sym_close_session(
  92           CryptoDevBackend *backend,
  93           uint64_t session_id,
  94           uint32_t queue_index, Error **errp)
  95{
  96    CryptoDevBackendClass *bc =
  97                      CRYPTODEV_BACKEND_GET_CLASS(backend);
  98
  99    if (bc->close_session) {
 100        return bc->close_session(backend, session_id, queue_index, errp);
 101    }
 102
 103    return -1;
 104}
 105
 106static int cryptodev_backend_sym_operation(
 107                 CryptoDevBackend *backend,
 108                 CryptoDevBackendSymOpInfo *op_info,
 109                 uint32_t queue_index, Error **errp)
 110{
 111    CryptoDevBackendClass *bc =
 112                      CRYPTODEV_BACKEND_GET_CLASS(backend);
 113
 114    if (bc->do_sym_op) {
 115        return bc->do_sym_op(backend, op_info, queue_index, errp);
 116    }
 117
 118    return -VIRTIO_CRYPTO_ERR;
 119}
 120
 121int cryptodev_backend_crypto_operation(
 122                 CryptoDevBackend *backend,
 123                 void *opaque,
 124                 uint32_t queue_index, Error **errp)
 125{
 126    VirtIOCryptoReq *req = opaque;
 127
 128    if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) {
 129        CryptoDevBackendSymOpInfo *op_info;
 130        op_info = req->u.sym_op_info;
 131
 132        return cryptodev_backend_sym_operation(backend,
 133                         op_info, queue_index, errp);
 134    } else {
 135        error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "",
 136                   req->flags);
 137       return -VIRTIO_CRYPTO_NOTSUPP;
 138    }
 139
 140    return -VIRTIO_CRYPTO_ERR;
 141}
 142
 143static void
 144cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
 145                             void *opaque, Error **errp)
 146{
 147    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 148    uint32_t value = backend->conf.peers.queues;
 149
 150    visit_type_uint32(v, name, &value, errp);
 151}
 152
 153static void
 154cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
 155                             void *opaque, Error **errp)
 156{
 157    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 158    Error *local_err = NULL;
 159    uint32_t value;
 160
 161    visit_type_uint32(v, name, &value, &local_err);
 162    if (local_err) {
 163        goto out;
 164    }
 165    if (!value) {
 166        error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
 167                   PRIu32 "'", object_get_typename(obj), name, value);
 168        goto out;
 169    }
 170    backend->conf.peers.queues = value;
 171out:
 172    error_propagate(errp, local_err);
 173}
 174
 175static void
 176cryptodev_backend_complete(UserCreatable *uc, Error **errp)
 177{
 178    CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
 179    CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
 180    Error *local_err = NULL;
 181
 182    if (bc->init) {
 183        bc->init(backend, &local_err);
 184        if (local_err) {
 185            goto out;
 186        }
 187    }
 188
 189    return;
 190
 191out:
 192    error_propagate(errp, local_err);
 193}
 194
 195void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used)
 196{
 197    backend->is_used = used;
 198}
 199
 200bool cryptodev_backend_is_used(CryptoDevBackend *backend)
 201{
 202    return backend->is_used;
 203}
 204
 205void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready)
 206{
 207    backend->ready = ready;
 208}
 209
 210bool cryptodev_backend_is_ready(CryptoDevBackend *backend)
 211{
 212    return backend->ready;
 213}
 214
 215static bool
 216cryptodev_backend_can_be_deleted(UserCreatable *uc)
 217{
 218    return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc));
 219}
 220
 221static void cryptodev_backend_instance_init(Object *obj)
 222{
 223    object_property_add(obj, "queues", "uint32",
 224                          cryptodev_backend_get_queues,
 225                          cryptodev_backend_set_queues,
 226                          NULL, NULL, NULL);
 227    /* Initialize devices' queues property to 1 */
 228    object_property_set_int(obj, 1, "queues", NULL);
 229}
 230
 231static void cryptodev_backend_finalize(Object *obj)
 232{
 233    CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
 234
 235    cryptodev_backend_cleanup(backend, NULL);
 236}
 237
 238static void
 239cryptodev_backend_class_init(ObjectClass *oc, void *data)
 240{
 241    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
 242
 243    ucc->complete = cryptodev_backend_complete;
 244    ucc->can_be_deleted = cryptodev_backend_can_be_deleted;
 245
 246    QTAILQ_INIT(&crypto_clients);
 247}
 248
 249static const TypeInfo cryptodev_backend_info = {
 250    .name = TYPE_CRYPTODEV_BACKEND,
 251    .parent = TYPE_OBJECT,
 252    .instance_size = sizeof(CryptoDevBackend),
 253    .instance_init = cryptodev_backend_instance_init,
 254    .instance_finalize = cryptodev_backend_finalize,
 255    .class_size = sizeof(CryptoDevBackendClass),
 256    .class_init = cryptodev_backend_class_init,
 257    .interfaces = (InterfaceInfo[]) {
 258        { TYPE_USER_CREATABLE },
 259        { }
 260    }
 261};
 262
 263static void
 264cryptodev_backend_register_types(void)
 265{
 266    type_register_static(&cryptodev_backend_info);
 267}
 268
 269type_init(cryptodev_backend_register_types);
 270