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