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 "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_new0(CryptoDevBackendClient, 1); 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 uint32_t value; 158 159 if (!visit_type_uint32(v, name, &value, errp)) { 160 return; 161 } 162 if (!value) { 163 error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu32 "'", 164 object_get_typename(obj), name, value); 165 return; 166 } 167 backend->conf.peers.queues = value; 168 } 169 170 static void 171 cryptodev_backend_complete(UserCreatable *uc, Error **errp) 172 { 173 CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc); 174 CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc); 175 176 if (bc->init) { 177 bc->init(backend, errp); 178 } 179 } 180 181 void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used) 182 { 183 backend->is_used = used; 184 } 185 186 bool cryptodev_backend_is_used(CryptoDevBackend *backend) 187 { 188 return backend->is_used; 189 } 190 191 void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready) 192 { 193 backend->ready = ready; 194 } 195 196 bool cryptodev_backend_is_ready(CryptoDevBackend *backend) 197 { 198 return backend->ready; 199 } 200 201 static bool 202 cryptodev_backend_can_be_deleted(UserCreatable *uc) 203 { 204 return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc)); 205 } 206 207 static void cryptodev_backend_instance_init(Object *obj) 208 { 209 /* Initialize devices' queues property to 1 */ 210 object_property_set_int(obj, "queues", 1, NULL); 211 } 212 213 static void cryptodev_backend_finalize(Object *obj) 214 { 215 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 216 217 cryptodev_backend_cleanup(backend, NULL); 218 } 219 220 static void 221 cryptodev_backend_class_init(ObjectClass *oc, void *data) 222 { 223 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 224 225 ucc->complete = cryptodev_backend_complete; 226 ucc->can_be_deleted = cryptodev_backend_can_be_deleted; 227 228 QTAILQ_INIT(&crypto_clients); 229 object_class_property_add(oc, "queues", "uint32", 230 cryptodev_backend_get_queues, 231 cryptodev_backend_set_queues, 232 NULL, NULL); 233 } 234 235 static const TypeInfo cryptodev_backend_info = { 236 .name = TYPE_CRYPTODEV_BACKEND, 237 .parent = TYPE_OBJECT, 238 .instance_size = sizeof(CryptoDevBackend), 239 .instance_init = cryptodev_backend_instance_init, 240 .instance_finalize = cryptodev_backend_finalize, 241 .class_size = sizeof(CryptoDevBackendClass), 242 .class_init = cryptodev_backend_class_init, 243 .interfaces = (InterfaceInfo[]) { 244 { TYPE_USER_CREATABLE }, 245 { } 246 } 247 }; 248 249 static void 250 cryptodev_backend_register_types(void) 251 { 252 type_register_static(&cryptodev_backend_info); 253 } 254 255 type_init(cryptodev_backend_register_types); 256