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