xref: /openbmc/qemu/backends/cryptodev-lkcf.c (revision bc831f37398b51dfe65d99a67bcff9352f84a9d2)
1 /*
2  * QEMU Cryptodev backend for QEMU cipher APIs
3  *
4  * Copyright (c) 2022 Bytedance.Inc
5  *
6  * Authors:
7  *    lei he <helei.sig11@bytedance.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 "crypto/cipher.h"
26 #include "crypto/akcipher.h"
27 #include "qapi/error.h"
28 #include "qemu/main-loop.h"
29 #include "qemu/thread.h"
30 #include "qemu/error-report.h"
31 #include "qemu/queue.h"
32 #include "qom/object.h"
33 #include "system/cryptodev.h"
34 #include "standard-headers/linux/virtio_crypto.h"
35 
36 #include <keyutils.h>
37 #include <sys/eventfd.h>
38 
39 /**
40  * @TYPE_CRYPTODEV_BACKEND_LKCF:
41  * name of backend that uses linux kernel crypto framework
42  */
43 #define TYPE_CRYPTODEV_BACKEND_LKCF "cryptodev-backend-lkcf"
44 
45 OBJECT_DECLARE_SIMPLE_TYPE(CryptoDevBackendLKCF, CRYPTODEV_BACKEND_LKCF)
46 
47 #define INVALID_KEY_ID -1
48 #define MAX_SESSIONS 256
49 #define NR_WORKER_THREAD 64
50 
51 #define KCTL_KEY_TYPE_PKEY "asymmetric"
52 /**
53  * Here the key is uploaded to the thread-keyring of worker thread, at least
54  * util linux-6.0:
55  * 1. process keyring seems to behave unexpectedly if main-thread does not
56  * create the keyring before creating any other thread.
57  * 2. at present, the guest kernel never perform multiple operations on a
58  * session.
59  * 3. it can reduce the load of the main-loop because the key passed by the
60  * guest kernel has been already checked.
61  */
62 #define KCTL_KEY_RING KEY_SPEC_THREAD_KEYRING
63 
64 typedef struct CryptoDevBackendLKCFSession {
65     uint8_t *key;
66     size_t keylen;
67     QCryptoAkCipherKeyType keytype;
68     QCryptoAkCipherOptions akcipher_opts;
69 } CryptoDevBackendLKCFSession;
70 
71 typedef struct CryptoDevLKCFTask CryptoDevLKCFTask;
72 struct CryptoDevLKCFTask {
73     CryptoDevBackendLKCFSession *sess;
74     CryptoDevBackendOpInfo *op_info;
75     CryptoDevCompletionFunc cb;
76     void *opaque;
77     int status;
78     CryptoDevBackendLKCF *lkcf;
79     QSIMPLEQ_ENTRY(CryptoDevLKCFTask) queue;
80 };
81 
82 typedef struct CryptoDevBackendLKCF {
83     CryptoDevBackend parent_obj;
84     CryptoDevBackendLKCFSession *sess[MAX_SESSIONS];
85     QSIMPLEQ_HEAD(, CryptoDevLKCFTask) requests;
86     QSIMPLEQ_HEAD(, CryptoDevLKCFTask) responses;
87     QemuMutex mutex;
88     QemuCond cond;
89     QemuMutex rsp_mutex;
90 
91     /**
92      * There is no async interface for asymmetric keys like AF_ALG sockets,
93      * we don't seem to have better way than create a lots of thread.
94      */
95     QemuThread worker_threads[NR_WORKER_THREAD];
96     bool running;
97     int eventfd;
98 } CryptoDevBackendLKCF;
99 
100 static void *cryptodev_lkcf_worker(void *arg);
101 static int cryptodev_lkcf_close_session(CryptoDevBackend *backend,
102                                         uint64_t session_id,
103                                         uint32_t queue_index,
104                                         CryptoDevCompletionFunc cb,
105                                         void *opaque);
106 
107 static void cryptodev_lkcf_handle_response(void *opaque)
108 {
109     CryptoDevBackendLKCF *lkcf = (CryptoDevBackendLKCF *)opaque;
110     QSIMPLEQ_HEAD(, CryptoDevLKCFTask) responses;
111     CryptoDevLKCFTask *task, *next;
112     eventfd_t nevent;
113 
114     QSIMPLEQ_INIT(&responses);
115     eventfd_read(lkcf->eventfd, &nevent);
116 
117     qemu_mutex_lock(&lkcf->rsp_mutex);
118     QSIMPLEQ_PREPEND(&responses, &lkcf->responses);
119     qemu_mutex_unlock(&lkcf->rsp_mutex);
120 
121     QSIMPLEQ_FOREACH_SAFE(task, &responses, queue, next) {
122         if (task->cb) {
123             task->cb(task->opaque, task->status);
124         }
125         g_free(task);
126     }
127 }
128 
129 static int cryptodev_lkcf_set_op_desc(QCryptoAkCipherOptions *opts,
130                                       char *key_desc,
131                                       size_t desc_len,
132                                       Error **errp)
133 {
134     QCryptoAkCipherOptionsRSA *rsa_opt;
135     if (opts->alg != QCRYPTO_AK_CIPHER_ALGO_RSA) {
136         error_setg(errp, "Unsupported alg: %u", opts->alg);
137         return -1;
138     }
139 
140     rsa_opt = &opts->u.rsa;
141     if (rsa_opt->padding_alg == QCRYPTO_RSA_PADDING_ALGO_PKCS1) {
142         snprintf(key_desc, desc_len, "enc=%s hash=%s",
143                  QCryptoRSAPaddingAlgo_str(rsa_opt->padding_alg),
144                  QCryptoHashAlgo_str(rsa_opt->hash_alg));
145 
146     } else {
147         snprintf(key_desc, desc_len, "enc=%s",
148                  QCryptoRSAPaddingAlgo_str(rsa_opt->padding_alg));
149     }
150     return 0;
151 }
152 
153 static int cryptodev_lkcf_set_rsa_opt(int virtio_padding_alg,
154                                       int virtio_hash_alg,
155                                       QCryptoAkCipherOptionsRSA *opt,
156                                       Error **errp)
157 {
158     if (virtio_padding_alg == VIRTIO_CRYPTO_RSA_PKCS1_PADDING) {
159         opt->padding_alg = QCRYPTO_RSA_PADDING_ALGO_PKCS1;
160 
161         switch (virtio_hash_alg) {
162         case VIRTIO_CRYPTO_RSA_MD5:
163             opt->hash_alg = QCRYPTO_HASH_ALGO_MD5;
164             break;
165 
166         case VIRTIO_CRYPTO_RSA_SHA1:
167             opt->hash_alg = QCRYPTO_HASH_ALGO_SHA1;
168             break;
169 
170         case VIRTIO_CRYPTO_RSA_SHA256:
171             opt->hash_alg = QCRYPTO_HASH_ALGO_SHA256;
172             break;
173 
174         case VIRTIO_CRYPTO_RSA_SHA512:
175             opt->hash_alg = QCRYPTO_HASH_ALGO_SHA512;
176             break;
177 
178         default:
179             error_setg(errp, "Unsupported rsa hash algo: %d", virtio_hash_alg);
180             return -1;
181         }
182         return 0;
183     }
184 
185     if (virtio_padding_alg == VIRTIO_CRYPTO_RSA_RAW_PADDING) {
186         opt->padding_alg = QCRYPTO_RSA_PADDING_ALGO_RAW;
187         return 0;
188     }
189 
190     error_setg(errp, "Unsupported rsa padding algo: %u", virtio_padding_alg);
191     return -1;
192 }
193 
194 static int cryptodev_lkcf_get_unused_session_index(CryptoDevBackendLKCF *lkcf)
195 {
196     size_t i;
197 
198     for (i = 0; i < MAX_SESSIONS; i++) {
199         if (lkcf->sess[i] == NULL) {
200             return i;
201         }
202     }
203     return -1;
204 }
205 
206 static void cryptodev_lkcf_init(CryptoDevBackend *backend, Error **errp)
207 {
208     /* Only support one queue */
209     int queues = backend->conf.peers.queues, i;
210     CryptoDevBackendClient *cc;
211     CryptoDevBackendLKCF *lkcf =
212         CRYPTODEV_BACKEND_LKCF(backend);
213 
214     if (queues != 1) {
215         error_setg(errp,
216                    "Only support one queue in cryptodev-builtin backend");
217         return;
218     }
219     lkcf->eventfd = eventfd(0, 0);
220     if (lkcf->eventfd < 0) {
221         error_setg(errp, "Failed to create eventfd: %d", errno);
222         return;
223     }
224 
225     cc = cryptodev_backend_new_client();
226     cc->info_str = g_strdup_printf("cryptodev-lkcf0");
227     cc->queue_index = 0;
228     cc->type = QCRYPTODEV_BACKEND_TYPE_LKCF;
229     backend->conf.peers.ccs[0] = cc;
230 
231     backend->conf.crypto_services =
232         1u << QCRYPTODEV_BACKEND_SERVICE_TYPE_AKCIPHER;
233     backend->conf.akcipher_algo = 1u << VIRTIO_CRYPTO_AKCIPHER_RSA;
234     lkcf->running = true;
235 
236     QSIMPLEQ_INIT(&lkcf->requests);
237     QSIMPLEQ_INIT(&lkcf->responses);
238     qemu_mutex_init(&lkcf->mutex);
239     qemu_mutex_init(&lkcf->rsp_mutex);
240     qemu_cond_init(&lkcf->cond);
241     for (i = 0; i < NR_WORKER_THREAD; i++) {
242         qemu_thread_create(&lkcf->worker_threads[i], "lkcf-worker",
243                            cryptodev_lkcf_worker, lkcf, 0);
244     }
245     qemu_set_fd_handler(
246         lkcf->eventfd, cryptodev_lkcf_handle_response, NULL, lkcf);
247     cryptodev_backend_set_ready(backend, true);
248 }
249 
250 static void cryptodev_lkcf_cleanup(CryptoDevBackend *backend, Error **errp)
251 {
252     CryptoDevBackendLKCF *lkcf = CRYPTODEV_BACKEND_LKCF(backend);
253     size_t i;
254     int queues = backend->conf.peers.queues;
255     CryptoDevBackendClient *cc;
256     CryptoDevLKCFTask *task, *next;
257 
258     qemu_mutex_lock(&lkcf->mutex);
259     lkcf->running = false;
260     qemu_mutex_unlock(&lkcf->mutex);
261     qemu_cond_broadcast(&lkcf->cond);
262 
263     close(lkcf->eventfd);
264     for (i = 0; i < NR_WORKER_THREAD; i++) {
265         qemu_thread_join(&lkcf->worker_threads[i]);
266     }
267 
268     QSIMPLEQ_FOREACH_SAFE(task, &lkcf->requests, queue, next) {
269         if (task->cb) {
270             task->cb(task->opaque, task->status);
271         }
272         g_free(task);
273     }
274 
275     QSIMPLEQ_FOREACH_SAFE(task, &lkcf->responses, queue, next) {
276         if (task->cb) {
277             task->cb(task->opaque, task->status);
278         }
279         g_free(task);
280     }
281 
282     qemu_mutex_destroy(&lkcf->mutex);
283     qemu_cond_destroy(&lkcf->cond);
284     qemu_mutex_destroy(&lkcf->rsp_mutex);
285 
286     for (i = 0; i < MAX_SESSIONS; i++) {
287         if (lkcf->sess[i] != NULL) {
288             cryptodev_lkcf_close_session(backend, i, 0, NULL, NULL);
289         }
290     }
291 
292     for (i = 0; i < queues; i++) {
293         cc = backend->conf.peers.ccs[i];
294         if (cc) {
295             cryptodev_backend_free_client(cc);
296             backend->conf.peers.ccs[i] = NULL;
297         }
298     }
299 
300     cryptodev_backend_set_ready(backend, false);
301 }
302 
303 static void cryptodev_lkcf_execute_task(CryptoDevLKCFTask *task)
304 {
305     CryptoDevBackendLKCFSession *session = task->sess;
306     CryptoDevBackendAsymOpInfo *asym_op_info;
307     bool kick = false;
308     int ret, status, op_code = task->op_info->op_code;
309     size_t p8info_len;
310     g_autofree uint8_t *p8info = NULL;
311     Error *local_error = NULL;
312     key_serial_t key_id = INVALID_KEY_ID;
313     char op_desc[64];
314     g_autoptr(QCryptoAkCipher) akcipher = NULL;
315 
316     /**
317      * We only offload private key session:
318      * 1. currently, the Linux kernel can only accept public key wrapped
319      * with X.509 certificates, but unfortunately the cost of making a
320      * ceritificate with public key is too expensive.
321      * 2. generally, public key related compution is fast, just compute it with
322      * thread-pool.
323      */
324     if (session->keytype == QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE) {
325         if (qcrypto_akcipher_export_p8info(&session->akcipher_opts,
326                                            session->key, session->keylen,
327                                            &p8info, &p8info_len,
328                                            &local_error) != 0 ||
329             cryptodev_lkcf_set_op_desc(&session->akcipher_opts, op_desc,
330                                        sizeof(op_desc), &local_error) != 0) {
331             error_report_err(local_error);
332             status = -VIRTIO_CRYPTO_ERR;
333             goto out;
334         } else {
335             key_id = add_key(KCTL_KEY_TYPE_PKEY, "lkcf-backend-priv-key",
336                              p8info, p8info_len, KCTL_KEY_RING);
337         }
338     }
339 
340     if (key_id < 0) {
341         if (!qcrypto_akcipher_supports(&session->akcipher_opts)) {
342             status = -VIRTIO_CRYPTO_NOTSUPP;
343             goto out;
344         }
345         akcipher = qcrypto_akcipher_new(&session->akcipher_opts,
346                                         session->keytype,
347                                         session->key, session->keylen,
348                                         &local_error);
349         if (!akcipher) {
350             error_report_err(local_error);
351             status = -VIRTIO_CRYPTO_ERR;
352             goto out;
353         }
354     }
355 
356     asym_op_info = task->op_info->u.asym_op_info;
357     switch (op_code) {
358     case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
359         if (key_id >= 0) {
360             ret = keyctl_pkey_encrypt(key_id, op_desc,
361                 asym_op_info->src, asym_op_info->src_len,
362                 asym_op_info->dst, asym_op_info->dst_len);
363         } else {
364             ret = qcrypto_akcipher_encrypt(akcipher,
365                 asym_op_info->src, asym_op_info->src_len,
366                 asym_op_info->dst, asym_op_info->dst_len, &local_error);
367         }
368         break;
369 
370     case VIRTIO_CRYPTO_AKCIPHER_DECRYPT:
371         if (key_id >= 0) {
372             ret = keyctl_pkey_decrypt(key_id, op_desc,
373                 asym_op_info->src, asym_op_info->src_len,
374                 asym_op_info->dst, asym_op_info->dst_len);
375         } else {
376             ret = qcrypto_akcipher_decrypt(akcipher,
377                 asym_op_info->src, asym_op_info->src_len,
378                 asym_op_info->dst, asym_op_info->dst_len, &local_error);
379         }
380         break;
381 
382     case VIRTIO_CRYPTO_AKCIPHER_SIGN:
383         if (key_id >= 0) {
384             ret = keyctl_pkey_sign(key_id, op_desc,
385                 asym_op_info->src, asym_op_info->src_len,
386                 asym_op_info->dst, asym_op_info->dst_len);
387         } else {
388             ret = qcrypto_akcipher_sign(akcipher,
389                 asym_op_info->src, asym_op_info->src_len,
390                 asym_op_info->dst, asym_op_info->dst_len, &local_error);
391         }
392         break;
393 
394     case VIRTIO_CRYPTO_AKCIPHER_VERIFY:
395         if (key_id >= 0) {
396             ret = keyctl_pkey_verify(key_id, op_desc,
397                 asym_op_info->src, asym_op_info->src_len,
398                 asym_op_info->dst, asym_op_info->dst_len);
399         } else {
400             ret = qcrypto_akcipher_verify(akcipher,
401                 asym_op_info->src, asym_op_info->src_len,
402                 asym_op_info->dst, asym_op_info->dst_len, &local_error);
403         }
404         break;
405 
406     default:
407         error_setg(&local_error, "Unknown opcode: %u", op_code);
408         status = -VIRTIO_CRYPTO_ERR;
409         goto out;
410     }
411 
412     if (ret < 0) {
413         if (!local_error) {
414             if (errno != EKEYREJECTED) {
415                 error_report("Failed do operation with keyctl: %d", errno);
416             }
417         } else {
418             error_report_err(local_error);
419         }
420         status = op_code == VIRTIO_CRYPTO_AKCIPHER_VERIFY ?
421             -VIRTIO_CRYPTO_KEY_REJECTED : -VIRTIO_CRYPTO_ERR;
422     } else {
423         status = VIRTIO_CRYPTO_OK;
424         asym_op_info->dst_len = ret;
425     }
426 
427 out:
428     if (key_id >= 0) {
429         keyctl_unlink(key_id, KCTL_KEY_RING);
430     }
431     task->status = status;
432 
433     qemu_mutex_lock(&task->lkcf->rsp_mutex);
434     if (QSIMPLEQ_EMPTY(&task->lkcf->responses)) {
435         kick = true;
436     }
437     QSIMPLEQ_INSERT_TAIL(&task->lkcf->responses, task, queue);
438     qemu_mutex_unlock(&task->lkcf->rsp_mutex);
439 
440     if (kick) {
441         eventfd_write(task->lkcf->eventfd, 1);
442     }
443 }
444 
445 static void *cryptodev_lkcf_worker(void *arg)
446 {
447     CryptoDevBackendLKCF *backend = (CryptoDevBackendLKCF *)arg;
448     CryptoDevLKCFTask *task;
449 
450     for (;;) {
451         task = NULL;
452         qemu_mutex_lock(&backend->mutex);
453         while (backend->running && QSIMPLEQ_EMPTY(&backend->requests)) {
454             qemu_cond_wait(&backend->cond, &backend->mutex);
455         }
456         if (backend->running) {
457             task = QSIMPLEQ_FIRST(&backend->requests);
458             QSIMPLEQ_REMOVE_HEAD(&backend->requests, queue);
459         }
460         qemu_mutex_unlock(&backend->mutex);
461 
462         /* stopped */
463         if (!task) {
464             break;
465         }
466         cryptodev_lkcf_execute_task(task);
467    }
468 
469    return NULL;
470 }
471 
472 static int cryptodev_lkcf_operation(
473     CryptoDevBackend *backend,
474     CryptoDevBackendOpInfo *op_info)
475 {
476     CryptoDevBackendLKCF *lkcf =
477         CRYPTODEV_BACKEND_LKCF(backend);
478     CryptoDevBackendLKCFSession *sess;
479     QCryptodevBackendAlgoType algtype = op_info->algtype;
480     CryptoDevLKCFTask *task;
481 
482     if (op_info->session_id >= MAX_SESSIONS ||
483         lkcf->sess[op_info->session_id] == NULL) {
484         error_report("Cannot find a valid session id: %" PRIu64 "",
485                      op_info->session_id);
486         return -VIRTIO_CRYPTO_INVSESS;
487     }
488 
489     sess = lkcf->sess[op_info->session_id];
490     if (algtype != QCRYPTODEV_BACKEND_ALGO_TYPE_ASYM) {
491         error_report("algtype not supported: %u", algtype);
492         return -VIRTIO_CRYPTO_NOTSUPP;
493     }
494 
495     task = g_new0(CryptoDevLKCFTask, 1);
496     task->op_info = op_info;
497     task->cb = op_info->cb;
498     task->opaque = op_info->opaque;
499     task->sess = sess;
500     task->lkcf = lkcf;
501     task->status = -VIRTIO_CRYPTO_ERR;
502 
503     qemu_mutex_lock(&lkcf->mutex);
504     QSIMPLEQ_INSERT_TAIL(&lkcf->requests, task, queue);
505     qemu_mutex_unlock(&lkcf->mutex);
506     qemu_cond_signal(&lkcf->cond);
507 
508     return VIRTIO_CRYPTO_OK;
509 }
510 
511 static int cryptodev_lkcf_create_asym_session(
512     CryptoDevBackendLKCF *lkcf,
513     CryptoDevBackendAsymSessionInfo *sess_info,
514     uint64_t *session_id)
515 {
516     Error *local_error = NULL;
517     int index;
518     g_autofree CryptoDevBackendLKCFSession *sess =
519         g_new0(CryptoDevBackendLKCFSession, 1);
520 
521     switch (sess_info->algo) {
522     case VIRTIO_CRYPTO_AKCIPHER_RSA:
523         sess->akcipher_opts.alg = QCRYPTO_AK_CIPHER_ALGO_RSA;
524         if (cryptodev_lkcf_set_rsa_opt(
525             sess_info->u.rsa.padding_algo, sess_info->u.rsa.hash_algo,
526             &sess->akcipher_opts.u.rsa, &local_error) != 0) {
527             error_report_err(local_error);
528             return -VIRTIO_CRYPTO_ERR;
529         }
530         break;
531 
532     default:
533         error_report("Unsupported asym alg %u", sess_info->algo);
534         return -VIRTIO_CRYPTO_NOTSUPP;
535     }
536 
537     switch (sess_info->keytype) {
538     case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
539         sess->keytype = QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC;
540         break;
541 
542     case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
543         sess->keytype = QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE;
544         break;
545 
546     default:
547         error_report("Unknown akcipher keytype: %u", sess_info->keytype);
548         return -VIRTIO_CRYPTO_ERR;
549     }
550 
551     index = cryptodev_lkcf_get_unused_session_index(lkcf);
552     if (index < 0) {
553         error_report("Total number of sessions created exceeds %u",
554                      MAX_SESSIONS);
555         return -VIRTIO_CRYPTO_ERR;
556     }
557 
558     sess->keylen = sess_info->keylen;
559     sess->key = g_malloc(sess_info->keylen);
560     memcpy(sess->key, sess_info->key, sess_info->keylen);
561 
562     lkcf->sess[index] = g_steal_pointer(&sess);
563     *session_id = index;
564 
565     return VIRTIO_CRYPTO_OK;
566 }
567 
568 static int cryptodev_lkcf_create_session(
569     CryptoDevBackend *backend,
570     CryptoDevBackendSessionInfo *sess_info,
571     uint32_t queue_index,
572     CryptoDevCompletionFunc cb,
573     void *opaque)
574 {
575     CryptoDevBackendAsymSessionInfo *asym_sess_info;
576     CryptoDevBackendLKCF *lkcf =
577         CRYPTODEV_BACKEND_LKCF(backend);
578     int ret;
579 
580     switch (sess_info->op_code) {
581     case VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION:
582         asym_sess_info = &sess_info->u.asym_sess_info;
583         ret = cryptodev_lkcf_create_asym_session(
584             lkcf, asym_sess_info, &sess_info->session_id);
585         break;
586 
587     default:
588         ret = -VIRTIO_CRYPTO_NOTSUPP;
589         error_report("Unsupported opcode: %" PRIu32 "",
590                      sess_info->op_code);
591         break;
592     }
593     if (cb) {
594         cb(opaque, ret);
595     }
596     return 0;
597 }
598 
599 static int cryptodev_lkcf_close_session(CryptoDevBackend *backend,
600                                         uint64_t session_id,
601                                         uint32_t queue_index,
602                                         CryptoDevCompletionFunc cb,
603                                         void *opaque)
604 {
605     CryptoDevBackendLKCF *lkcf = CRYPTODEV_BACKEND_LKCF(backend);
606     CryptoDevBackendLKCFSession *session;
607 
608     assert(session_id < MAX_SESSIONS && lkcf->sess[session_id]);
609     session = lkcf->sess[session_id];
610     lkcf->sess[session_id] = NULL;
611 
612     g_free(session->key);
613     g_free(session);
614 
615     if (cb) {
616         cb(opaque, VIRTIO_CRYPTO_OK);
617     }
618     return 0;
619 }
620 
621 static void cryptodev_lkcf_class_init(ObjectClass *oc, const void *data)
622 {
623     CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_CLASS(oc);
624 
625     bc->init = cryptodev_lkcf_init;
626     bc->cleanup = cryptodev_lkcf_cleanup;
627     bc->create_session = cryptodev_lkcf_create_session;
628     bc->close_session = cryptodev_lkcf_close_session;
629     bc->do_op = cryptodev_lkcf_operation;
630 }
631 
632 static const TypeInfo cryptodev_builtin_info = {
633     .name = TYPE_CRYPTODEV_BACKEND_LKCF,
634     .parent = TYPE_CRYPTODEV_BACKEND,
635     .class_init = cryptodev_lkcf_class_init,
636     .instance_size = sizeof(CryptoDevBackendLKCF),
637 };
638 
639 static void cryptodev_lkcf_register_types(void)
640 {
641     type_register_static(&cryptodev_builtin_info);
642 }
643 
644 type_init(cryptodev_lkcf_register_types);
645