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_create_session( 76 CryptoDevBackend *backend, 77 CryptoDevBackendSessionInfo *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_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_operation( 106 CryptoDevBackend *backend, 107 CryptoDevBackendOpInfo *op_info, 108 uint32_t queue_index, Error **errp) 109 { 110 CryptoDevBackendClass *bc = 111 CRYPTODEV_BACKEND_GET_CLASS(backend); 112 113 if (bc->do_op) { 114 return bc->do_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 CryptoDevBackendOpInfo *op_info = &req->op_info; 127 enum CryptoDevBackendAlgType algtype = req->flags; 128 129 if ((algtype != CRYPTODEV_BACKEND_ALG_SYM) 130 && (algtype != CRYPTODEV_BACKEND_ALG_ASYM)) { 131 error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "", 132 algtype); 133 134 return -VIRTIO_CRYPTO_NOTSUPP; 135 } 136 137 return cryptodev_backend_operation(backend, op_info, queue_index, errp); 138 } 139 140 static void 141 cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name, 142 void *opaque, Error **errp) 143 { 144 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 145 uint32_t value = backend->conf.peers.queues; 146 147 visit_type_uint32(v, name, &value, errp); 148 } 149 150 static void 151 cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name, 152 void *opaque, Error **errp) 153 { 154 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 155 uint32_t value; 156 157 if (!visit_type_uint32(v, name, &value, errp)) { 158 return; 159 } 160 if (!value) { 161 error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu32 "'", 162 object_get_typename(obj), name, value); 163 return; 164 } 165 backend->conf.peers.queues = value; 166 } 167 168 static void 169 cryptodev_backend_complete(UserCreatable *uc, Error **errp) 170 { 171 CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc); 172 CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc); 173 174 if (bc->init) { 175 bc->init(backend, errp); 176 } 177 } 178 179 void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used) 180 { 181 backend->is_used = used; 182 } 183 184 bool cryptodev_backend_is_used(CryptoDevBackend *backend) 185 { 186 return backend->is_used; 187 } 188 189 void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready) 190 { 191 backend->ready = ready; 192 } 193 194 bool cryptodev_backend_is_ready(CryptoDevBackend *backend) 195 { 196 return backend->ready; 197 } 198 199 static bool 200 cryptodev_backend_can_be_deleted(UserCreatable *uc) 201 { 202 return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc)); 203 } 204 205 static void cryptodev_backend_instance_init(Object *obj) 206 { 207 /* Initialize devices' queues property to 1 */ 208 object_property_set_int(obj, "queues", 1, NULL); 209 } 210 211 static void cryptodev_backend_finalize(Object *obj) 212 { 213 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); 214 215 cryptodev_backend_cleanup(backend, NULL); 216 } 217 218 static void 219 cryptodev_backend_class_init(ObjectClass *oc, void *data) 220 { 221 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); 222 223 ucc->complete = cryptodev_backend_complete; 224 ucc->can_be_deleted = cryptodev_backend_can_be_deleted; 225 226 QTAILQ_INIT(&crypto_clients); 227 object_class_property_add(oc, "queues", "uint32", 228 cryptodev_backend_get_queues, 229 cryptodev_backend_set_queues, 230 NULL, NULL); 231 } 232 233 static const TypeInfo cryptodev_backend_info = { 234 .name = TYPE_CRYPTODEV_BACKEND, 235 .parent = TYPE_OBJECT, 236 .instance_size = sizeof(CryptoDevBackend), 237 .instance_init = cryptodev_backend_instance_init, 238 .instance_finalize = cryptodev_backend_finalize, 239 .class_size = sizeof(CryptoDevBackendClass), 240 .class_init = cryptodev_backend_class_init, 241 .interfaces = (InterfaceInfo[]) { 242 { TYPE_USER_CREATABLE }, 243 { } 244 } 245 }; 246 247 static void 248 cryptodev_backend_register_types(void) 249 { 250 type_register_static(&cryptodev_backend_info); 251 } 252 253 type_init(cryptodev_backend_register_types); 254