qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

cryptodev.c (7111B)


      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.1 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 "qapi/error.h"
     27 #include "qapi/visitor.h"
     28 #include "qemu/config-file.h"
     29 #include "qemu/error-report.h"
     30 #include "qom/object_interfaces.h"
     31 #include "hw/virtio/virtio-crypto.h"
     32 
     33 
     34 static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients;
     35 
     36 
     37 CryptoDevBackendClient *
     38 cryptodev_backend_new_client(const char *model,
     39                                     const char *name)
     40 {
     41     CryptoDevBackendClient *cc;
     42 
     43     cc = g_new0(CryptoDevBackendClient, 1);
     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 
     54 void 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 
     64 void 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 
     76 int cryptodev_backend_create_session(
     77            CryptoDevBackend *backend,
     78            CryptoDevBackendSessionInfo *sess_info,
     79            uint32_t queue_index,
     80            CryptoDevCompletionFunc cb,
     81            void *opaque)
     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, cb, opaque);
     88     }
     89     return -VIRTIO_CRYPTO_NOTSUPP;
     90 }
     91 
     92 int cryptodev_backend_close_session(
     93            CryptoDevBackend *backend,
     94            uint64_t session_id,
     95            uint32_t queue_index,
     96            CryptoDevCompletionFunc cb,
     97            void *opaque)
     98 {
     99     CryptoDevBackendClass *bc =
    100                       CRYPTODEV_BACKEND_GET_CLASS(backend);
    101 
    102     if (bc->close_session) {
    103         return bc->close_session(backend, session_id, queue_index, cb, opaque);
    104     }
    105     return -VIRTIO_CRYPTO_NOTSUPP;
    106 }
    107 
    108 static int cryptodev_backend_operation(
    109                  CryptoDevBackend *backend,
    110                  CryptoDevBackendOpInfo *op_info,
    111                  uint32_t queue_index,
    112                  CryptoDevCompletionFunc cb,
    113                  void *opaque)
    114 {
    115     CryptoDevBackendClass *bc =
    116                       CRYPTODEV_BACKEND_GET_CLASS(backend);
    117 
    118     if (bc->do_op) {
    119         return bc->do_op(backend, op_info, queue_index, cb, opaque);
    120     }
    121     return -VIRTIO_CRYPTO_NOTSUPP;
    122 }
    123 
    124 int cryptodev_backend_crypto_operation(
    125                  CryptoDevBackend *backend,
    126                  void *opaque1,
    127                  uint32_t queue_index,
    128                  CryptoDevCompletionFunc cb, void *opaque2)
    129 {
    130     VirtIOCryptoReq *req = opaque1;
    131     CryptoDevBackendOpInfo *op_info = &req->op_info;
    132     enum CryptoDevBackendAlgType algtype = req->flags;
    133 
    134     if ((algtype != CRYPTODEV_BACKEND_ALG_SYM)
    135         && (algtype != CRYPTODEV_BACKEND_ALG_ASYM)) {
    136         error_report("Unsupported cryptodev alg type: %" PRIu32 "", algtype);
    137         return -VIRTIO_CRYPTO_NOTSUPP;
    138     }
    139 
    140     return cryptodev_backend_operation(backend, op_info, queue_index,
    141                                        cb, opaque2);
    142 }
    143 
    144 static void
    145 cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
    146                              void *opaque, Error **errp)
    147 {
    148     CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
    149     uint32_t value = backend->conf.peers.queues;
    150 
    151     visit_type_uint32(v, name, &value, errp);
    152 }
    153 
    154 static void
    155 cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
    156                              void *opaque, Error **errp)
    157 {
    158     CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
    159     uint32_t value;
    160 
    161     if (!visit_type_uint32(v, name, &value, errp)) {
    162         return;
    163     }
    164     if (!value) {
    165         error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu32 "'",
    166                    object_get_typename(obj), name, value);
    167         return;
    168     }
    169     backend->conf.peers.queues = value;
    170 }
    171 
    172 static void
    173 cryptodev_backend_complete(UserCreatable *uc, Error **errp)
    174 {
    175     CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
    176     CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
    177 
    178     if (bc->init) {
    179         bc->init(backend, errp);
    180     }
    181 }
    182 
    183 void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used)
    184 {
    185     backend->is_used = used;
    186 }
    187 
    188 bool cryptodev_backend_is_used(CryptoDevBackend *backend)
    189 {
    190     return backend->is_used;
    191 }
    192 
    193 void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready)
    194 {
    195     backend->ready = ready;
    196 }
    197 
    198 bool cryptodev_backend_is_ready(CryptoDevBackend *backend)
    199 {
    200     return backend->ready;
    201 }
    202 
    203 static bool
    204 cryptodev_backend_can_be_deleted(UserCreatable *uc)
    205 {
    206     return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc));
    207 }
    208 
    209 static void cryptodev_backend_instance_init(Object *obj)
    210 {
    211     /* Initialize devices' queues property to 1 */
    212     object_property_set_int(obj, "queues", 1, NULL);
    213 }
    214 
    215 static void cryptodev_backend_finalize(Object *obj)
    216 {
    217     CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
    218 
    219     cryptodev_backend_cleanup(backend, NULL);
    220 }
    221 
    222 static void
    223 cryptodev_backend_class_init(ObjectClass *oc, void *data)
    224 {
    225     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
    226 
    227     ucc->complete = cryptodev_backend_complete;
    228     ucc->can_be_deleted = cryptodev_backend_can_be_deleted;
    229 
    230     QTAILQ_INIT(&crypto_clients);
    231     object_class_property_add(oc, "queues", "uint32",
    232                               cryptodev_backend_get_queues,
    233                               cryptodev_backend_set_queues,
    234                               NULL, NULL);
    235 }
    236 
    237 static const TypeInfo cryptodev_backend_info = {
    238     .name = TYPE_CRYPTODEV_BACKEND,
    239     .parent = TYPE_OBJECT,
    240     .instance_size = sizeof(CryptoDevBackend),
    241     .instance_init = cryptodev_backend_instance_init,
    242     .instance_finalize = cryptodev_backend_finalize,
    243     .class_size = sizeof(CryptoDevBackendClass),
    244     .class_init = cryptodev_backend_class_init,
    245     .interfaces = (InterfaceInfo[]) {
    246         { TYPE_USER_CREATABLE },
    247         { }
    248     }
    249 };
    250 
    251 static void
    252 cryptodev_backend_register_types(void)
    253 {
    254     type_register_static(&cryptodev_backend_info);
    255 }
    256 
    257 type_init(cryptodev_backend_register_types);