master
c 648 lines 19.8 KB
Raw
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_errno(errp, errno, "Failed to create eventfd");
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 if (!cryptodev_backend_is_ready(backend)) {
259 return;
260 }
261
262 qemu_mutex_lock(&lkcf->mutex);
263 lkcf->running = false;
264 qemu_mutex_unlock(&lkcf->mutex);
265 qemu_cond_broadcast(&lkcf->cond);
266
267 close(lkcf->eventfd);
268 for (i = 0; i < NR_WORKER_THREAD; i++) {
269 qemu_thread_join(&lkcf->worker_threads[i]);
270 }
271
272 QSIMPLEQ_FOREACH_SAFE(task, &lkcf->requests, queue, next) {
273 if (task->cb) {
274 task->cb(task->opaque, task->status);
275 }
276 g_free(task);
277 }
278
279 QSIMPLEQ_FOREACH_SAFE(task, &lkcf->responses, queue, next) {
280 if (task->cb) {
281 task->cb(task->opaque, task->status);
282 }
283 g_free(task);
284 }
285
286 qemu_mutex_destroy(&lkcf->mutex);
287 qemu_cond_destroy(&lkcf->cond);
288 qemu_mutex_destroy(&lkcf->rsp_mutex);
289
290 for (i = 0; i < MAX_SESSIONS; i++) {
291 if (lkcf->sess[i] != NULL) {
292 cryptodev_lkcf_close_session(backend, i, 0, NULL, NULL);
293 }
294 }
295
296 for (i = 0; i < queues; i++) {
297 cc = backend->conf.peers.ccs[i];
298 if (cc) {
299 cryptodev_backend_free_client(cc);
300 backend->conf.peers.ccs[i] = NULL;
301 }
302 }
303
304 cryptodev_backend_set_ready(backend, false);
305 }
306
307 static void cryptodev_lkcf_execute_task(CryptoDevLKCFTask *task)
308 {
309 CryptoDevBackendLKCFSession *session = task->sess;
310 CryptoDevBackendAsymOpInfo *asym_op_info;
311 bool kick = false;
312 int ret, status, op_code = task->op_info->op_code;
313 size_t p8info_len;
314 g_autofree uint8_t *p8info = NULL;
315 Error *local_error = NULL;
316 key_serial_t key_id = INVALID_KEY_ID;
317 char op_desc[64];
318 g_autoptr(QCryptoAkCipher) akcipher = NULL;
319
320 /**
321 * We only offload private key session:
322 * 1. currently, the Linux kernel can only accept public key wrapped
323 * with X.509 certificates, but unfortunately the cost of making a
324 * ceritificate with public key is too expensive.
325 * 2. generally, public key related compution is fast, just compute it with
326 * thread-pool.
327 */
328 if (session->keytype == QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE) {
329 if (qcrypto_akcipher_export_p8info(&session->akcipher_opts,
330 session->key, session->keylen,
331 &p8info, &p8info_len,
332 &local_error) != 0 ||
333 cryptodev_lkcf_set_op_desc(&session->akcipher_opts, op_desc,
334 sizeof(op_desc), &local_error) != 0) {
335 error_report_err(local_error);
336 status = -VIRTIO_CRYPTO_ERR;
337 goto out;
338 } else {
339 key_id = add_key(KCTL_KEY_TYPE_PKEY, "lkcf-backend-priv-key",
340 p8info, p8info_len, KCTL_KEY_RING);
341 }
342 }
343
344 if (key_id < 0) {
345 if (!qcrypto_akcipher_supports(&session->akcipher_opts)) {
346 status = -VIRTIO_CRYPTO_NOTSUPP;
347 goto out;
348 }
349 akcipher = qcrypto_akcipher_new(&session->akcipher_opts,
350 session->keytype,
351 session->key, session->keylen,
352 &local_error);
353 if (!akcipher) {
354 error_report_err(local_error);
355 status = -VIRTIO_CRYPTO_ERR;
356 goto out;
357 }
358 }
359
360 asym_op_info = task->op_info->u.asym_op_info;
361 switch (op_code) {
362 case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
363 if (key_id >= 0) {
364 ret = keyctl_pkey_encrypt(key_id, op_desc,
365 asym_op_info->src, asym_op_info->src_len,
366 asym_op_info->dst, asym_op_info->dst_len);
367 } else {
368 ret = qcrypto_akcipher_encrypt(akcipher,
369 asym_op_info->src, asym_op_info->src_len,
370 asym_op_info->dst, asym_op_info->dst_len, &local_error);
371 }
372 break;
373
374 case VIRTIO_CRYPTO_AKCIPHER_DECRYPT:
375 if (key_id >= 0) {
376 ret = keyctl_pkey_decrypt(key_id, op_desc,
377 asym_op_info->src, asym_op_info->src_len,
378 asym_op_info->dst, asym_op_info->dst_len);
379 } else {
380 ret = qcrypto_akcipher_decrypt(akcipher,
381 asym_op_info->src, asym_op_info->src_len,
382 asym_op_info->dst, asym_op_info->dst_len, &local_error);
383 }
384 break;
385
386 case VIRTIO_CRYPTO_AKCIPHER_SIGN:
387 if (key_id >= 0) {
388 ret = keyctl_pkey_sign(key_id, op_desc,
389 asym_op_info->src, asym_op_info->src_len,
390 asym_op_info->dst, asym_op_info->dst_len);
391 } else {
392 ret = qcrypto_akcipher_sign(akcipher,
393 asym_op_info->src, asym_op_info->src_len,
394 asym_op_info->dst, asym_op_info->dst_len, &local_error);
395 }
396 break;
397
398 case VIRTIO_CRYPTO_AKCIPHER_VERIFY:
399 if (key_id >= 0) {
400 ret = keyctl_pkey_verify(key_id, op_desc,
401 asym_op_info->src, asym_op_info->src_len,
402 asym_op_info->dst, asym_op_info->dst_len);
403 } else {
404 ret = qcrypto_akcipher_verify(akcipher,
405 asym_op_info->src, asym_op_info->src_len,
406 asym_op_info->dst, asym_op_info->dst_len, &local_error);
407 }
408 break;
409
410 default:
411 error_setg(&local_error, "Unknown opcode: %u", op_code);
412 status = -VIRTIO_CRYPTO_ERR;
413 goto out;
414 }
415
416 if (ret < 0) {
417 if (!local_error) {
418 if (errno != EKEYREJECTED) {
419 error_report("Failed do operation with keyctl: %d", errno);
420 }
421 } else {
422 error_report_err(local_error);
423 }
424 status = op_code == VIRTIO_CRYPTO_AKCIPHER_VERIFY ?
425 -VIRTIO_CRYPTO_KEY_REJECTED : -VIRTIO_CRYPTO_ERR;
426 } else {
427 status = VIRTIO_CRYPTO_OK;
428 asym_op_info->dst_len = ret;
429 }
430
431 out:
432 if (key_id >= 0) {
433 keyctl_unlink(key_id, KCTL_KEY_RING);
434 }
435 task->status = status;
436
437 qemu_mutex_lock(&task->lkcf->rsp_mutex);
438 if (QSIMPLEQ_EMPTY(&task->lkcf->responses)) {
439 kick = true;
440 }
441 QSIMPLEQ_INSERT_TAIL(&task->lkcf->responses, task, queue);
442 qemu_mutex_unlock(&task->lkcf->rsp_mutex);
443
444 if (kick) {
445 eventfd_write(task->lkcf->eventfd, 1);
446 }
447 }
448
449 static void *cryptodev_lkcf_worker(void *arg)
450 {
451 CryptoDevBackendLKCF *backend = (CryptoDevBackendLKCF *)arg;
452 CryptoDevLKCFTask *task;
453
454 for (;;) {
455 task = NULL;
456 qemu_mutex_lock(&backend->mutex);
457 while (backend->running && QSIMPLEQ_EMPTY(&backend->requests)) {
458 qemu_cond_wait(&backend->cond, &backend->mutex);
459 }
460 if (backend->running) {
461 task = QSIMPLEQ_FIRST(&backend->requests);
462 QSIMPLEQ_REMOVE_HEAD(&backend->requests, queue);
463 }
464 qemu_mutex_unlock(&backend->mutex);
465
466 /* stopped */
467 if (!task) {
468 break;
469 }
470 cryptodev_lkcf_execute_task(task);
471 }
472
473 return NULL;
474 }
475
476 static int cryptodev_lkcf_operation(
477 CryptoDevBackend *backend,
478 CryptoDevBackendOpInfo *op_info)
479 {
480 CryptoDevBackendLKCF *lkcf =
481 CRYPTODEV_BACKEND_LKCF(backend);
482 CryptoDevBackendLKCFSession *sess;
483 QCryptodevBackendAlgoType algtype = op_info->algtype;
484 CryptoDevLKCFTask *task;
485
486 if (op_info->session_id >= MAX_SESSIONS ||
487 lkcf->sess[op_info->session_id] == NULL) {
488 error_report("Cannot find a valid session id: %" PRIu64 "",
489 op_info->session_id);
490 return -VIRTIO_CRYPTO_INVSESS;
491 }
492
493 sess = lkcf->sess[op_info->session_id];
494 if (algtype != QCRYPTODEV_BACKEND_ALGO_TYPE_ASYM) {
495 error_report("algtype not supported: %u", algtype);
496 return -VIRTIO_CRYPTO_NOTSUPP;
497 }
498
499 task = g_new0(CryptoDevLKCFTask, 1);
500 task->op_info = op_info;
501 task->cb = op_info->cb;
502 task->opaque = op_info->opaque;
503 task->sess = sess;
504 task->lkcf = lkcf;
505 task->status = -VIRTIO_CRYPTO_ERR;
506
507 qemu_mutex_lock(&lkcf->mutex);
508 QSIMPLEQ_INSERT_TAIL(&lkcf->requests, task, queue);
509 qemu_mutex_unlock(&lkcf->mutex);
510 qemu_cond_signal(&lkcf->cond);
511
512 return VIRTIO_CRYPTO_OK;
513 }
514
515 static int cryptodev_lkcf_create_asym_session(
516 CryptoDevBackendLKCF *lkcf,
517 CryptoDevBackendAsymSessionInfo *sess_info,
518 uint64_t *session_id)
519 {
520 Error *local_error = NULL;
521 int index;
522 g_autofree CryptoDevBackendLKCFSession *sess =
523 g_new0(CryptoDevBackendLKCFSession, 1);
524
525 switch (sess_info->algo) {
526 case VIRTIO_CRYPTO_AKCIPHER_RSA:
527 sess->akcipher_opts.alg = QCRYPTO_AK_CIPHER_ALGO_RSA;
528 if (cryptodev_lkcf_set_rsa_opt(
529 sess_info->u.rsa.padding_algo, sess_info->u.rsa.hash_algo,
530 &sess->akcipher_opts.u.rsa, &local_error) != 0) {
531 error_report_err(local_error);
532 return -VIRTIO_CRYPTO_ERR;
533 }
534 break;
535
536 default:
537 error_report("Unsupported asym alg %u", sess_info->algo);
538 return -VIRTIO_CRYPTO_NOTSUPP;
539 }
540
541 switch (sess_info->keytype) {
542 case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC:
543 sess->keytype = QCRYPTO_AK_CIPHER_KEY_TYPE_PUBLIC;
544 break;
545
546 case VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE:
547 sess->keytype = QCRYPTO_AK_CIPHER_KEY_TYPE_PRIVATE;
548 break;
549
550 default:
551 error_report("Unknown akcipher keytype: %u", sess_info->keytype);
552 return -VIRTIO_CRYPTO_ERR;
553 }
554
555 index = cryptodev_lkcf_get_unused_session_index(lkcf);
556 if (index < 0) {
557 error_report("Total number of sessions created exceeds %u",
558 MAX_SESSIONS);
559 return -VIRTIO_CRYPTO_ERR;
560 }
561
562 sess->keylen = sess_info->keylen;
563 sess->key = g_malloc(sess_info->keylen);
564 memcpy(sess->key, sess_info->key, sess_info->keylen);
565
566 lkcf->sess[index] = g_steal_pointer(&sess);
567 *session_id = index;
568
569 return VIRTIO_CRYPTO_OK;
570 }
571
572 static int cryptodev_lkcf_create_session(
573 CryptoDevBackend *backend,
574 CryptoDevBackendSessionInfo *sess_info,
575 uint32_t queue_index,
576 CryptoDevCompletionFunc cb,
577 void *opaque)
578 {
579 CryptoDevBackendAsymSessionInfo *asym_sess_info;
580 CryptoDevBackendLKCF *lkcf =
581 CRYPTODEV_BACKEND_LKCF(backend);
582 int ret;
583
584 switch (sess_info->op_code) {
585 case VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION:
586 asym_sess_info = &sess_info->u.asym_sess_info;
587 ret = cryptodev_lkcf_create_asym_session(
588 lkcf, asym_sess_info, &sess_info->session_id);
589 break;
590
591 default:
592 ret = -VIRTIO_CRYPTO_NOTSUPP;
593 error_report("Unsupported opcode: %" PRIu32 "",
594 sess_info->op_code);
595 break;
596 }
597 if (cb) {
598 cb(opaque, ret);
599 }
600 return 0;
601 }
602
603 static int cryptodev_lkcf_close_session(CryptoDevBackend *backend,
604 uint64_t session_id,
605 uint32_t queue_index,
606 CryptoDevCompletionFunc cb,
607 void *opaque)
608 {
609 CryptoDevBackendLKCF *lkcf = CRYPTODEV_BACKEND_LKCF(backend);
610 CryptoDevBackendLKCFSession *session;
611
612 assert(session_id < MAX_SESSIONS && lkcf->sess[session_id]);
613 session = lkcf->sess[session_id];
614 lkcf->sess[session_id] = NULL;
615
616 g_free(session->key);
617 g_free(session);
618
619 if (cb) {
620 cb(opaque, VIRTIO_CRYPTO_OK);
621 }
622 return 0;
623 }
624
625 static void cryptodev_lkcf_class_init(ObjectClass *oc, const void *data)
626 {
627 CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_CLASS(oc);
628
629 bc->init = cryptodev_lkcf_init;
630 bc->cleanup = cryptodev_lkcf_cleanup;
631 bc->create_session = cryptodev_lkcf_create_session;
632 bc->close_session = cryptodev_lkcf_close_session;
633 bc->do_op = cryptodev_lkcf_operation;
634 }
635
636 static const TypeInfo cryptodev_builtin_info = {
637 .name = TYPE_CRYPTODEV_BACKEND_LKCF,
638 .parent = TYPE_CRYPTODEV_BACKEND,
639 .class_init = cryptodev_lkcf_class_init,
640 .instance_size = sizeof(CryptoDevBackendLKCF),
641 };
642
643 static void cryptodev_lkcf_register_types(void)
644 {
645 type_register_static(&cryptodev_builtin_info);
646 }
647
648 type_init(cryptodev_lkcf_register_types);