]> git.proxmox.com Git - mirror_qemu.git/blob - backends/cryptodev.c
cryptodev: Introduce 'query-cryptodev' QMP command
[mirror_qemu.git] / backends / cryptodev.c
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/qapi-commands-cryptodev.h"
28 #include "qapi/visitor.h"
29 #include "qemu/config-file.h"
30 #include "qemu/error-report.h"
31 #include "qom/object_interfaces.h"
32 #include "hw/virtio/virtio-crypto.h"
33
34
35 static QTAILQ_HEAD(, CryptoDevBackendClient) crypto_clients;
36
37 static int qmp_query_cryptodev_foreach(Object *obj, void *data)
38 {
39 CryptoDevBackend *backend;
40 QCryptodevInfoList **infolist = data;
41 uint32_t services, i;
42
43 if (!object_dynamic_cast(obj, TYPE_CRYPTODEV_BACKEND)) {
44 return 0;
45 }
46
47 QCryptodevInfo *info = g_new0(QCryptodevInfo, 1);
48 info->id = g_strdup(object_get_canonical_path_component(obj));
49
50 backend = CRYPTODEV_BACKEND(obj);
51 services = backend->conf.crypto_services;
52 for (i = 0; i < QCRYPTODEV_BACKEND_SERVICE__MAX; i++) {
53 if (services & (1 << i)) {
54 QAPI_LIST_PREPEND(info->service, i);
55 }
56 }
57
58 for (i = 0; i < backend->conf.peers.queues; i++) {
59 CryptoDevBackendClient *cc = backend->conf.peers.ccs[i];
60 QCryptodevBackendClient *client = g_new0(QCryptodevBackendClient, 1);
61
62 client->queue = cc->queue_index;
63 client->type = cc->type;
64 QAPI_LIST_PREPEND(info->client, client);
65 }
66
67 QAPI_LIST_PREPEND(*infolist, info);
68
69 return 0;
70 }
71
72 QCryptodevInfoList *qmp_query_cryptodev(Error **errp)
73 {
74 QCryptodevInfoList *list = NULL;
75 Object *objs = container_get(object_get_root(), "/objects");
76
77 object_child_foreach(objs, qmp_query_cryptodev_foreach, &list);
78
79 return list;
80 }
81
82 CryptoDevBackendClient *cryptodev_backend_new_client(void)
83 {
84 CryptoDevBackendClient *cc;
85
86 cc = g_new0(CryptoDevBackendClient, 1);
87 QTAILQ_INSERT_TAIL(&crypto_clients, cc, next);
88
89 return cc;
90 }
91
92 void cryptodev_backend_free_client(
93 CryptoDevBackendClient *cc)
94 {
95 QTAILQ_REMOVE(&crypto_clients, cc, next);
96 g_free(cc->info_str);
97 g_free(cc);
98 }
99
100 void cryptodev_backend_cleanup(
101 CryptoDevBackend *backend,
102 Error **errp)
103 {
104 CryptoDevBackendClass *bc =
105 CRYPTODEV_BACKEND_GET_CLASS(backend);
106
107 if (bc->cleanup) {
108 bc->cleanup(backend, errp);
109 }
110 }
111
112 int cryptodev_backend_create_session(
113 CryptoDevBackend *backend,
114 CryptoDevBackendSessionInfo *sess_info,
115 uint32_t queue_index,
116 CryptoDevCompletionFunc cb,
117 void *opaque)
118 {
119 CryptoDevBackendClass *bc =
120 CRYPTODEV_BACKEND_GET_CLASS(backend);
121
122 if (bc->create_session) {
123 return bc->create_session(backend, sess_info, queue_index, cb, opaque);
124 }
125 return -VIRTIO_CRYPTO_NOTSUPP;
126 }
127
128 int cryptodev_backend_close_session(
129 CryptoDevBackend *backend,
130 uint64_t session_id,
131 uint32_t queue_index,
132 CryptoDevCompletionFunc cb,
133 void *opaque)
134 {
135 CryptoDevBackendClass *bc =
136 CRYPTODEV_BACKEND_GET_CLASS(backend);
137
138 if (bc->close_session) {
139 return bc->close_session(backend, session_id, queue_index, cb, opaque);
140 }
141 return -VIRTIO_CRYPTO_NOTSUPP;
142 }
143
144 static int cryptodev_backend_operation(
145 CryptoDevBackend *backend,
146 CryptoDevBackendOpInfo *op_info,
147 uint32_t queue_index,
148 CryptoDevCompletionFunc cb,
149 void *opaque)
150 {
151 CryptoDevBackendClass *bc =
152 CRYPTODEV_BACKEND_GET_CLASS(backend);
153
154 if (bc->do_op) {
155 return bc->do_op(backend, op_info, queue_index, cb, opaque);
156 }
157 return -VIRTIO_CRYPTO_NOTSUPP;
158 }
159
160 int cryptodev_backend_crypto_operation(
161 CryptoDevBackend *backend,
162 void *opaque1,
163 uint32_t queue_index,
164 CryptoDevCompletionFunc cb, void *opaque2)
165 {
166 VirtIOCryptoReq *req = opaque1;
167 CryptoDevBackendOpInfo *op_info = &req->op_info;
168 QCryptodevBackendAlgType algtype = req->flags;
169
170 if ((algtype != QCRYPTODEV_BACKEND_ALG_SYM)
171 && (algtype != QCRYPTODEV_BACKEND_ALG_ASYM)) {
172 error_report("Unsupported cryptodev alg type: %" PRIu32 "", algtype);
173 return -VIRTIO_CRYPTO_NOTSUPP;
174 }
175
176 return cryptodev_backend_operation(backend, op_info, queue_index,
177 cb, opaque2);
178 }
179
180 static void
181 cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
182 void *opaque, Error **errp)
183 {
184 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
185 uint32_t value = backend->conf.peers.queues;
186
187 visit_type_uint32(v, name, &value, errp);
188 }
189
190 static void
191 cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
192 void *opaque, Error **errp)
193 {
194 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
195 uint32_t value;
196
197 if (!visit_type_uint32(v, name, &value, errp)) {
198 return;
199 }
200 if (!value) {
201 error_setg(errp, "Property '%s.%s' doesn't take value '%" PRIu32 "'",
202 object_get_typename(obj), name, value);
203 return;
204 }
205 backend->conf.peers.queues = value;
206 }
207
208 static void
209 cryptodev_backend_complete(UserCreatable *uc, Error **errp)
210 {
211 CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc);
212 CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc);
213
214 if (bc->init) {
215 bc->init(backend, errp);
216 }
217 }
218
219 void cryptodev_backend_set_used(CryptoDevBackend *backend, bool used)
220 {
221 backend->is_used = used;
222 }
223
224 bool cryptodev_backend_is_used(CryptoDevBackend *backend)
225 {
226 return backend->is_used;
227 }
228
229 void cryptodev_backend_set_ready(CryptoDevBackend *backend, bool ready)
230 {
231 backend->ready = ready;
232 }
233
234 bool cryptodev_backend_is_ready(CryptoDevBackend *backend)
235 {
236 return backend->ready;
237 }
238
239 static bool
240 cryptodev_backend_can_be_deleted(UserCreatable *uc)
241 {
242 return !cryptodev_backend_is_used(CRYPTODEV_BACKEND(uc));
243 }
244
245 static void cryptodev_backend_instance_init(Object *obj)
246 {
247 /* Initialize devices' queues property to 1 */
248 object_property_set_int(obj, "queues", 1, NULL);
249 }
250
251 static void cryptodev_backend_finalize(Object *obj)
252 {
253 CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj);
254
255 cryptodev_backend_cleanup(backend, NULL);
256 }
257
258 static void
259 cryptodev_backend_class_init(ObjectClass *oc, void *data)
260 {
261 UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
262
263 ucc->complete = cryptodev_backend_complete;
264 ucc->can_be_deleted = cryptodev_backend_can_be_deleted;
265
266 QTAILQ_INIT(&crypto_clients);
267 object_class_property_add(oc, "queues", "uint32",
268 cryptodev_backend_get_queues,
269 cryptodev_backend_set_queues,
270 NULL, NULL);
271 }
272
273 static const TypeInfo cryptodev_backend_info = {
274 .name = TYPE_CRYPTODEV_BACKEND,
275 .parent = TYPE_OBJECT,
276 .instance_size = sizeof(CryptoDevBackend),
277 .instance_init = cryptodev_backend_instance_init,
278 .instance_finalize = cryptodev_backend_finalize,
279 .class_size = sizeof(CryptoDevBackendClass),
280 .class_init = cryptodev_backend_class_init,
281 .interfaces = (InterfaceInfo[]) {
282 { TYPE_USER_CREATABLE },
283 { }
284 }
285 };
286
287 static void
288 cryptodev_backend_register_types(void)
289 {
290 type_register_static(&cryptodev_backend_info);
291 }
292
293 type_init(cryptodev_backend_register_types);