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