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 36 static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients; 37 38 39 CryptoDevBackendClient * 40 cryptodev_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 56 void 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 66 void 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 78 int64_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 93 int 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 108 static 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 123 int 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 145 static void 146 cryptodev_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 155 static void 156 cryptodev_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; 173 out: 174 error_propagate(errp, local_err); 175 } 176 177 static void 178 cryptodev_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 193 out: 194 error_propagate(errp, local_err); 195 } 196 197 void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used) 198 { 199 backend->is_used = used; 200 } 201 202 bool cryptodev_backend_is_used(CryptoDevBackend *backend) 203 { 204 return backend->is_used; 205 } 206 207 void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready) 208 { 209 backend->ready = ready; 210 } 211 212 bool cryptodev_backend_is_ready(CryptoDevBackend *backend) 213 { 214 return backend->ready; 215 } 216 217 static bool 218 cryptodev_backend_can_be_deleted(UserCreatable *uc, Error **errp) 219 { 220 return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc)); 221 } 222 223 static 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 233 static void cryptodev_backend_finalize(Object *obj) 234 { 235 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 236 237 cryptodev_backend_cleanup(backend, NULL); 238 } 239 240 static void 241 cryptodev_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 251 static 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 265 static void 266 cryptodev_backend_register_types(void) 267 { 268 type_register_static(&cryptodev_backend_info); 269 } 270 271 type_init(cryptodev_backend_register_types); 272