xref: /openbmc/qemu/backends/cryptodev.c (revision 999c789f)
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);
249