1 /* 2 * Virtio crypto Support 3 * 4 * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. 5 * 6 * Authors: 7 * Gonglei <arei.gonglei@huawei.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or 10 * (at your option) any later version. See the COPYING file in the 11 * top-level directory. 12 */ 13 #include "qemu/osdep.h" 14 #include "qemu/iov.h" 15 #include "hw/qdev.h" 16 #include "qapi/error.h" 17 #include "qemu/error-report.h" 18 19 #include "hw/virtio/virtio.h" 20 #include "hw/virtio/virtio-crypto.h" 21 #include "hw/virtio/virtio-access.h" 22 #include "standard-headers/linux/virtio_ids.h" 23 24 #define VIRTIO_CRYPTO_VM_VERSION 1 25 26 /* 27 * Transfer virtqueue index to crypto queue index. 28 * The control virtqueue is after the data virtqueues 29 * so the input value doesn't need to be adjusted 30 */ 31 static inline int virtio_crypto_vq2q(int queue_index) 32 { 33 return queue_index; 34 } 35 36 static int 37 virtio_crypto_cipher_session_helper(VirtIODevice *vdev, 38 CryptoDevBackendSymSessionInfo *info, 39 struct virtio_crypto_cipher_session_para *cipher_para, 40 struct iovec **iov, unsigned int *out_num) 41 { 42 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); 43 unsigned int num = *out_num; 44 45 info->cipher_alg = ldl_le_p(&cipher_para->algo); 46 info->key_len = ldl_le_p(&cipher_para->keylen); 47 info->direction = ldl_le_p(&cipher_para->op); 48 DPRINTF("cipher_alg=%" PRIu32 ", info->direction=%" PRIu32 "\n", 49 info->cipher_alg, info->direction); 50 51 if (info->key_len > vcrypto->conf.max_cipher_key_len) { 52 error_report("virtio-crypto length of cipher key is too big: %u", 53 info->key_len); 54 return -VIRTIO_CRYPTO_ERR; 55 } 56 /* Get cipher key */ 57 if (info->key_len > 0) { 58 size_t s; 59 DPRINTF("keylen=%" PRIu32 "\n", info->key_len); 60 61 info->cipher_key = g_malloc(info->key_len); 62 s = iov_to_buf(*iov, num, 0, info->cipher_key, info->key_len); 63 if (unlikely(s != info->key_len)) { 64 virtio_error(vdev, "virtio-crypto cipher key incorrect"); 65 return -EFAULT; 66 } 67 iov_discard_front(iov, &num, info->key_len); 68 *out_num = num; 69 } 70 71 return 0; 72 } 73 74 static int64_t 75 virtio_crypto_create_sym_session(VirtIOCrypto *vcrypto, 76 struct virtio_crypto_sym_create_session_req *sess_req, 77 uint32_t queue_id, 78 uint32_t opcode, 79 struct iovec *iov, unsigned int out_num) 80 { 81 VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto); 82 CryptoDevBackendSymSessionInfo info; 83 int64_t session_id; 84 int queue_index; 85 uint32_t op_type; 86 Error *local_err = NULL; 87 int ret; 88 89 memset(&info, 0, sizeof(info)); 90 op_type = ldl_le_p(&sess_req->op_type); 91 info.op_type = op_type; 92 info.op_code = opcode; 93 94 if (op_type == VIRTIO_CRYPTO_SYM_OP_CIPHER) { 95 ret = virtio_crypto_cipher_session_helper(vdev, &info, 96 &sess_req->u.cipher.para, 97 &iov, &out_num); 98 if (ret < 0) { 99 goto err; 100 } 101 } else if (op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) { 102 size_t s; 103 /* cipher part */ 104 ret = virtio_crypto_cipher_session_helper(vdev, &info, 105 &sess_req->u.chain.para.cipher_param, 106 &iov, &out_num); 107 if (ret < 0) { 108 goto err; 109 } 110 /* hash part */ 111 info.alg_chain_order = ldl_le_p( 112 &sess_req->u.chain.para.alg_chain_order); 113 info.add_len = ldl_le_p(&sess_req->u.chain.para.aad_len); 114 info.hash_mode = ldl_le_p(&sess_req->u.chain.para.hash_mode); 115 if (info.hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH) { 116 info.hash_alg = ldl_le_p(&sess_req->u.chain.para.u.mac_param.algo); 117 info.auth_key_len = ldl_le_p( 118 &sess_req->u.chain.para.u.mac_param.auth_key_len); 119 info.hash_result_len = ldl_le_p( 120 &sess_req->u.chain.para.u.mac_param.hash_result_len); 121 if (info.auth_key_len > vcrypto->conf.max_auth_key_len) { 122 error_report("virtio-crypto length of auth key is too big: %u", 123 info.auth_key_len); 124 ret = -VIRTIO_CRYPTO_ERR; 125 goto err; 126 } 127 /* get auth key */ 128 if (info.auth_key_len > 0) { 129 DPRINTF("auth_keylen=%" PRIu32 "\n", info.auth_key_len); 130 info.auth_key = g_malloc(info.auth_key_len); 131 s = iov_to_buf(iov, out_num, 0, info.auth_key, 132 info.auth_key_len); 133 if (unlikely(s != info.auth_key_len)) { 134 virtio_error(vdev, 135 "virtio-crypto authenticated key incorrect"); 136 ret = -EFAULT; 137 goto err; 138 } 139 iov_discard_front(&iov, &out_num, info.auth_key_len); 140 } 141 } else if (info.hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN) { 142 info.hash_alg = ldl_le_p( 143 &sess_req->u.chain.para.u.hash_param.algo); 144 info.hash_result_len = ldl_le_p( 145 &sess_req->u.chain.para.u.hash_param.hash_result_len); 146 } else { 147 /* VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED */ 148 error_report("unsupported hash mode"); 149 ret = -VIRTIO_CRYPTO_NOTSUPP; 150 goto err; 151 } 152 } else { 153 /* VIRTIO_CRYPTO_SYM_OP_NONE */ 154 error_report("unsupported cipher op_type: VIRTIO_CRYPTO_SYM_OP_NONE"); 155 ret = -VIRTIO_CRYPTO_NOTSUPP; 156 goto err; 157 } 158 159 queue_index = virtio_crypto_vq2q(queue_id); 160 session_id = cryptodev_backend_sym_create_session( 161 vcrypto->cryptodev, 162 &info, queue_index, &local_err); 163 if (session_id >= 0) { 164 DPRINTF("create session_id=%" PRIu64 " successfully\n", 165 session_id); 166 167 ret = session_id; 168 } else { 169 if (local_err) { 170 error_report_err(local_err); 171 } 172 ret = -VIRTIO_CRYPTO_ERR; 173 } 174 175 err: 176 g_free(info.cipher_key); 177 g_free(info.auth_key); 178 return ret; 179 } 180 181 static uint8_t 182 virtio_crypto_handle_close_session(VirtIOCrypto *vcrypto, 183 struct virtio_crypto_destroy_session_req *close_sess_req, 184 uint32_t queue_id) 185 { 186 int ret; 187 uint64_t session_id; 188 uint32_t status; 189 Error *local_err = NULL; 190 191 session_id = ldq_le_p(&close_sess_req->session_id); 192 DPRINTF("close session, id=%" PRIu64 "\n", session_id); 193 194 ret = cryptodev_backend_sym_close_session( 195 vcrypto->cryptodev, session_id, queue_id, &local_err); 196 if (ret == 0) { 197 status = VIRTIO_CRYPTO_OK; 198 } else { 199 if (local_err) { 200 error_report_err(local_err); 201 } else { 202 error_report("destroy session failed"); 203 } 204 status = VIRTIO_CRYPTO_ERR; 205 } 206 207 return status; 208 } 209 210 static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq) 211 { 212 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); 213 struct virtio_crypto_op_ctrl_req ctrl; 214 VirtQueueElement *elem; 215 struct iovec *in_iov; 216 struct iovec *out_iov; 217 unsigned in_num; 218 unsigned out_num; 219 uint32_t queue_id; 220 uint32_t opcode; 221 struct virtio_crypto_session_input input; 222 int64_t session_id; 223 uint8_t status; 224 size_t s; 225 226 for (;;) { 227 elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); 228 if (!elem) { 229 break; 230 } 231 if (elem->out_num < 1 || elem->in_num < 1) { 232 virtio_error(vdev, "virtio-crypto ctrl missing headers"); 233 virtqueue_detach_element(vq, elem, 0); 234 g_free(elem); 235 break; 236 } 237 238 out_num = elem->out_num; 239 out_iov = elem->out_sg; 240 in_num = elem->in_num; 241 in_iov = elem->in_sg; 242 if (unlikely(iov_to_buf(out_iov, out_num, 0, &ctrl, sizeof(ctrl)) 243 != sizeof(ctrl))) { 244 virtio_error(vdev, "virtio-crypto request ctrl_hdr too short"); 245 virtqueue_detach_element(vq, elem, 0); 246 g_free(elem); 247 break; 248 } 249 iov_discard_front(&out_iov, &out_num, sizeof(ctrl)); 250 251 opcode = ldl_le_p(&ctrl.header.opcode); 252 queue_id = ldl_le_p(&ctrl.header.queue_id); 253 254 switch (opcode) { 255 case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION: 256 memset(&input, 0, sizeof(input)); 257 session_id = virtio_crypto_create_sym_session(vcrypto, 258 &ctrl.u.sym_create_session, 259 queue_id, opcode, 260 out_iov, out_num); 261 /* Serious errors, need to reset virtio crypto device */ 262 if (session_id == -EFAULT) { 263 virtqueue_detach_element(vq, elem, 0); 264 break; 265 } else if (session_id == -VIRTIO_CRYPTO_NOTSUPP) { 266 stl_le_p(&input.status, VIRTIO_CRYPTO_NOTSUPP); 267 } else if (session_id == -VIRTIO_CRYPTO_ERR) { 268 stl_le_p(&input.status, VIRTIO_CRYPTO_ERR); 269 } else { 270 /* Set the session id */ 271 stq_le_p(&input.session_id, session_id); 272 stl_le_p(&input.status, VIRTIO_CRYPTO_OK); 273 } 274 275 s = iov_from_buf(in_iov, in_num, 0, &input, sizeof(input)); 276 if (unlikely(s != sizeof(input))) { 277 virtio_error(vdev, "virtio-crypto input incorrect"); 278 virtqueue_detach_element(vq, elem, 0); 279 break; 280 } 281 virtqueue_push(vq, elem, sizeof(input)); 282 virtio_notify(vdev, vq); 283 break; 284 case VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION: 285 case VIRTIO_CRYPTO_HASH_DESTROY_SESSION: 286 case VIRTIO_CRYPTO_MAC_DESTROY_SESSION: 287 case VIRTIO_CRYPTO_AEAD_DESTROY_SESSION: 288 status = virtio_crypto_handle_close_session(vcrypto, 289 &ctrl.u.destroy_session, queue_id); 290 /* The status only occupy one byte, we can directly use it */ 291 s = iov_from_buf(in_iov, in_num, 0, &status, sizeof(status)); 292 if (unlikely(s != sizeof(status))) { 293 virtio_error(vdev, "virtio-crypto status incorrect"); 294 virtqueue_detach_element(vq, elem, 0); 295 break; 296 } 297 virtqueue_push(vq, elem, sizeof(status)); 298 virtio_notify(vdev, vq); 299 break; 300 case VIRTIO_CRYPTO_HASH_CREATE_SESSION: 301 case VIRTIO_CRYPTO_MAC_CREATE_SESSION: 302 case VIRTIO_CRYPTO_AEAD_CREATE_SESSION: 303 default: 304 error_report("virtio-crypto unsupported ctrl opcode: %d", opcode); 305 memset(&input, 0, sizeof(input)); 306 stl_le_p(&input.status, VIRTIO_CRYPTO_NOTSUPP); 307 s = iov_from_buf(in_iov, in_num, 0, &input, sizeof(input)); 308 if (unlikely(s != sizeof(input))) { 309 virtio_error(vdev, "virtio-crypto input incorrect"); 310 virtqueue_detach_element(vq, elem, 0); 311 break; 312 } 313 virtqueue_push(vq, elem, sizeof(input)); 314 virtio_notify(vdev, vq); 315 316 break; 317 } /* end switch case */ 318 319 g_free(elem); 320 } /* end for loop */ 321 } 322 323 static void virtio_crypto_init_request(VirtIOCrypto *vcrypto, VirtQueue *vq, 324 VirtIOCryptoReq *req) 325 { 326 req->vcrypto = vcrypto; 327 req->vq = vq; 328 req->in = NULL; 329 req->in_iov = NULL; 330 req->in_num = 0; 331 req->in_len = 0; 332 req->flags = CRYPTODEV_BACKEND_ALG__MAX; 333 req->u.sym_op_info = NULL; 334 } 335 336 static void virtio_crypto_free_request(VirtIOCryptoReq *req) 337 { 338 if (req) { 339 if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) { 340 g_free(req->u.sym_op_info); 341 } 342 g_free(req); 343 } 344 } 345 346 static void 347 virtio_crypto_sym_input_data_helper(VirtIODevice *vdev, 348 VirtIOCryptoReq *req, 349 uint32_t status, 350 CryptoDevBackendSymOpInfo *sym_op_info) 351 { 352 size_t s, len; 353 354 if (status != VIRTIO_CRYPTO_OK) { 355 return; 356 } 357 358 len = sym_op_info->dst_len; 359 /* Save the cipher result */ 360 s = iov_from_buf(req->in_iov, req->in_num, 0, sym_op_info->dst, len); 361 if (s != len) { 362 virtio_error(vdev, "virtio-crypto dest data incorrect"); 363 return; 364 } 365 366 iov_discard_front(&req->in_iov, &req->in_num, len); 367 368 if (sym_op_info->op_type == 369 VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) { 370 /* Save the digest result */ 371 s = iov_from_buf(req->in_iov, req->in_num, 0, 372 sym_op_info->digest_result, 373 sym_op_info->digest_result_len); 374 if (s != sym_op_info->digest_result_len) { 375 virtio_error(vdev, "virtio-crypto digest result incorrect"); 376 } 377 } 378 } 379 380 static void virtio_crypto_req_complete(VirtIOCryptoReq *req, uint8_t status) 381 { 382 VirtIOCrypto *vcrypto = req->vcrypto; 383 VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto); 384 385 if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) { 386 virtio_crypto_sym_input_data_helper(vdev, req, status, 387 req->u.sym_op_info); 388 } 389 stb_p(&req->in->status, status); 390 virtqueue_push(req->vq, &req->elem, req->in_len); 391 virtio_notify(vdev, req->vq); 392 } 393 394 static VirtIOCryptoReq * 395 virtio_crypto_get_request(VirtIOCrypto *s, VirtQueue *vq) 396 { 397 VirtIOCryptoReq *req = virtqueue_pop(vq, sizeof(VirtIOCryptoReq)); 398 399 if (req) { 400 virtio_crypto_init_request(s, vq, req); 401 } 402 return req; 403 } 404 405 static CryptoDevBackendSymOpInfo * 406 virtio_crypto_sym_op_helper(VirtIODevice *vdev, 407 struct virtio_crypto_cipher_para *cipher_para, 408 struct virtio_crypto_alg_chain_data_para *alg_chain_para, 409 struct iovec *iov, unsigned int out_num) 410 { 411 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); 412 CryptoDevBackendSymOpInfo *op_info; 413 uint32_t src_len = 0, dst_len = 0; 414 uint32_t iv_len = 0; 415 uint32_t aad_len = 0, hash_result_len = 0; 416 uint32_t hash_start_src_offset = 0, len_to_hash = 0; 417 uint32_t cipher_start_src_offset = 0, len_to_cipher = 0; 418 419 size_t max_len, curr_size = 0; 420 size_t s; 421 422 /* Plain cipher */ 423 if (cipher_para) { 424 iv_len = ldl_le_p(&cipher_para->iv_len); 425 src_len = ldl_le_p(&cipher_para->src_data_len); 426 dst_len = ldl_le_p(&cipher_para->dst_data_len); 427 } else if (alg_chain_para) { /* Algorithm chain */ 428 iv_len = ldl_le_p(&alg_chain_para->iv_len); 429 src_len = ldl_le_p(&alg_chain_para->src_data_len); 430 dst_len = ldl_le_p(&alg_chain_para->dst_data_len); 431 432 aad_len = ldl_le_p(&alg_chain_para->aad_len); 433 hash_result_len = ldl_le_p(&alg_chain_para->hash_result_len); 434 hash_start_src_offset = ldl_le_p( 435 &alg_chain_para->hash_start_src_offset); 436 cipher_start_src_offset = ldl_le_p( 437 &alg_chain_para->cipher_start_src_offset); 438 len_to_cipher = ldl_le_p(&alg_chain_para->len_to_cipher); 439 len_to_hash = ldl_le_p(&alg_chain_para->len_to_hash); 440 } else { 441 return NULL; 442 } 443 444 max_len = iv_len + aad_len + src_len + dst_len + hash_result_len; 445 if (unlikely(max_len > vcrypto->conf.max_size)) { 446 virtio_error(vdev, "virtio-crypto too big length"); 447 return NULL; 448 } 449 450 op_info = g_malloc0(sizeof(CryptoDevBackendSymOpInfo) + max_len); 451 op_info->iv_len = iv_len; 452 op_info->src_len = src_len; 453 op_info->dst_len = dst_len; 454 op_info->aad_len = aad_len; 455 op_info->digest_result_len = hash_result_len; 456 op_info->hash_start_src_offset = hash_start_src_offset; 457 op_info->len_to_hash = len_to_hash; 458 op_info->cipher_start_src_offset = cipher_start_src_offset; 459 op_info->len_to_cipher = len_to_cipher; 460 /* Handle the initilization vector */ 461 if (op_info->iv_len > 0) { 462 DPRINTF("iv_len=%" PRIu32 "\n", op_info->iv_len); 463 op_info->iv = op_info->data + curr_size; 464 465 s = iov_to_buf(iov, out_num, 0, op_info->iv, op_info->iv_len); 466 if (unlikely(s != op_info->iv_len)) { 467 virtio_error(vdev, "virtio-crypto iv incorrect"); 468 goto err; 469 } 470 iov_discard_front(&iov, &out_num, op_info->iv_len); 471 curr_size += op_info->iv_len; 472 } 473 474 /* Handle additional authentication data if exists */ 475 if (op_info->aad_len > 0) { 476 DPRINTF("aad_len=%" PRIu32 "\n", op_info->aad_len); 477 op_info->aad_data = op_info->data + curr_size; 478 479 s = iov_to_buf(iov, out_num, 0, op_info->aad_data, op_info->aad_len); 480 if (unlikely(s != op_info->aad_len)) { 481 virtio_error(vdev, "virtio-crypto additional auth data incorrect"); 482 goto err; 483 } 484 iov_discard_front(&iov, &out_num, op_info->aad_len); 485 486 curr_size += op_info->aad_len; 487 } 488 489 /* Handle the source data */ 490 if (op_info->src_len > 0) { 491 DPRINTF("src_len=%" PRIu32 "\n", op_info->src_len); 492 op_info->src = op_info->data + curr_size; 493 494 s = iov_to_buf(iov, out_num, 0, op_info->src, op_info->src_len); 495 if (unlikely(s != op_info->src_len)) { 496 virtio_error(vdev, "virtio-crypto source data incorrect"); 497 goto err; 498 } 499 iov_discard_front(&iov, &out_num, op_info->src_len); 500 501 curr_size += op_info->src_len; 502 } 503 504 /* Handle the destination data */ 505 op_info->dst = op_info->data + curr_size; 506 curr_size += op_info->dst_len; 507 508 DPRINTF("dst_len=%" PRIu32 "\n", op_info->dst_len); 509 510 /* Handle the hash digest result */ 511 if (hash_result_len > 0) { 512 DPRINTF("hash_result_len=%" PRIu32 "\n", hash_result_len); 513 op_info->digest_result = op_info->data + curr_size; 514 } 515 516 return op_info; 517 518 err: 519 g_free(op_info); 520 return NULL; 521 } 522 523 static int 524 virtio_crypto_handle_sym_req(VirtIOCrypto *vcrypto, 525 struct virtio_crypto_sym_data_req *req, 526 CryptoDevBackendSymOpInfo **sym_op_info, 527 struct iovec *iov, unsigned int out_num) 528 { 529 VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto); 530 uint32_t op_type; 531 CryptoDevBackendSymOpInfo *op_info; 532 533 op_type = ldl_le_p(&req->op_type); 534 535 if (op_type == VIRTIO_CRYPTO_SYM_OP_CIPHER) { 536 op_info = virtio_crypto_sym_op_helper(vdev, &req->u.cipher.para, 537 NULL, iov, out_num); 538 if (!op_info) { 539 return -EFAULT; 540 } 541 op_info->op_type = op_type; 542 } else if (op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) { 543 op_info = virtio_crypto_sym_op_helper(vdev, NULL, 544 &req->u.chain.para, 545 iov, out_num); 546 if (!op_info) { 547 return -EFAULT; 548 } 549 op_info->op_type = op_type; 550 } else { 551 /* VIRTIO_CRYPTO_SYM_OP_NONE */ 552 error_report("virtio-crypto unsupported cipher type"); 553 return -VIRTIO_CRYPTO_NOTSUPP; 554 } 555 556 *sym_op_info = op_info; 557 558 return 0; 559 } 560 561 static int 562 virtio_crypto_handle_request(VirtIOCryptoReq *request) 563 { 564 VirtIOCrypto *vcrypto = request->vcrypto; 565 VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto); 566 VirtQueueElement *elem = &request->elem; 567 int queue_index = virtio_crypto_vq2q(virtio_get_queue_index(request->vq)); 568 struct virtio_crypto_op_data_req req; 569 int ret; 570 struct iovec *in_iov; 571 struct iovec *out_iov; 572 unsigned in_num; 573 unsigned out_num; 574 uint32_t opcode; 575 uint8_t status = VIRTIO_CRYPTO_ERR; 576 uint64_t session_id; 577 CryptoDevBackendSymOpInfo *sym_op_info = NULL; 578 Error *local_err = NULL; 579 580 if (elem->out_num < 1 || elem->in_num < 1) { 581 virtio_error(vdev, "virtio-crypto dataq missing headers"); 582 return -1; 583 } 584 585 out_num = elem->out_num; 586 out_iov = elem->out_sg; 587 in_num = elem->in_num; 588 in_iov = elem->in_sg; 589 if (unlikely(iov_to_buf(out_iov, out_num, 0, &req, sizeof(req)) 590 != sizeof(req))) { 591 virtio_error(vdev, "virtio-crypto request outhdr too short"); 592 return -1; 593 } 594 iov_discard_front(&out_iov, &out_num, sizeof(req)); 595 596 if (in_iov[in_num - 1].iov_len < 597 sizeof(struct virtio_crypto_inhdr)) { 598 virtio_error(vdev, "virtio-crypto request inhdr too short"); 599 return -1; 600 } 601 /* We always touch the last byte, so just see how big in_iov is. */ 602 request->in_len = iov_size(in_iov, in_num); 603 request->in = (void *)in_iov[in_num - 1].iov_base 604 + in_iov[in_num - 1].iov_len 605 - sizeof(struct virtio_crypto_inhdr); 606 iov_discard_back(in_iov, &in_num, sizeof(struct virtio_crypto_inhdr)); 607 608 /* 609 * The length of operation result, including dest_data 610 * and digest_result if exists. 611 */ 612 request->in_num = in_num; 613 request->in_iov = in_iov; 614 615 opcode = ldl_le_p(&req.header.opcode); 616 session_id = ldq_le_p(&req.header.session_id); 617 618 switch (opcode) { 619 case VIRTIO_CRYPTO_CIPHER_ENCRYPT: 620 case VIRTIO_CRYPTO_CIPHER_DECRYPT: 621 ret = virtio_crypto_handle_sym_req(vcrypto, 622 &req.u.sym_req, 623 &sym_op_info, 624 out_iov, out_num); 625 /* Serious errors, need to reset virtio crypto device */ 626 if (ret == -EFAULT) { 627 return -1; 628 } else if (ret == -VIRTIO_CRYPTO_NOTSUPP) { 629 virtio_crypto_req_complete(request, VIRTIO_CRYPTO_NOTSUPP); 630 virtio_crypto_free_request(request); 631 } else { 632 sym_op_info->session_id = session_id; 633 634 /* Set request's parameter */ 635 request->flags = CRYPTODEV_BACKEND_ALG_SYM; 636 request->u.sym_op_info = sym_op_info; 637 ret = cryptodev_backend_crypto_operation(vcrypto->cryptodev, 638 request, queue_index, &local_err); 639 if (ret < 0) { 640 status = -ret; 641 if (local_err) { 642 error_report_err(local_err); 643 } 644 } else { /* ret == VIRTIO_CRYPTO_OK */ 645 status = ret; 646 } 647 virtio_crypto_req_complete(request, status); 648 virtio_crypto_free_request(request); 649 } 650 break; 651 case VIRTIO_CRYPTO_HASH: 652 case VIRTIO_CRYPTO_MAC: 653 case VIRTIO_CRYPTO_AEAD_ENCRYPT: 654 case VIRTIO_CRYPTO_AEAD_DECRYPT: 655 default: 656 error_report("virtio-crypto unsupported dataq opcode: %u", 657 opcode); 658 virtio_crypto_req_complete(request, VIRTIO_CRYPTO_NOTSUPP); 659 virtio_crypto_free_request(request); 660 } 661 662 return 0; 663 } 664 665 static void virtio_crypto_handle_dataq(VirtIODevice *vdev, VirtQueue *vq) 666 { 667 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); 668 VirtIOCryptoReq *req; 669 670 while ((req = virtio_crypto_get_request(vcrypto, vq))) { 671 if (virtio_crypto_handle_request(req) < 0) { 672 virtqueue_detach_element(req->vq, &req->elem, 0); 673 virtio_crypto_free_request(req); 674 break; 675 } 676 } 677 } 678 679 static void virtio_crypto_dataq_bh(void *opaque) 680 { 681 VirtIOCryptoQueue *q = opaque; 682 VirtIOCrypto *vcrypto = q->vcrypto; 683 VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto); 684 685 /* This happens when device was stopped but BH wasn't. */ 686 if (!vdev->vm_running) { 687 return; 688 } 689 690 /* Just in case the driver is not ready on more */ 691 if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) { 692 return; 693 } 694 695 virtio_crypto_handle_dataq(vdev, q->dataq); 696 virtio_queue_set_notification(q->dataq, 1); 697 } 698 699 static void 700 virtio_crypto_handle_dataq_bh(VirtIODevice *vdev, VirtQueue *vq) 701 { 702 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); 703 VirtIOCryptoQueue *q = 704 &vcrypto->vqs[virtio_crypto_vq2q(virtio_get_queue_index(vq))]; 705 706 /* This happens when device was stopped but VCPU wasn't. */ 707 if (!vdev->vm_running) { 708 return; 709 } 710 virtio_queue_set_notification(vq, 0); 711 qemu_bh_schedule(q->dataq_bh); 712 } 713 714 static uint64_t virtio_crypto_get_features(VirtIODevice *vdev, 715 uint64_t features, 716 Error **errp) 717 { 718 return features; 719 } 720 721 static void virtio_crypto_reset(VirtIODevice *vdev) 722 { 723 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); 724 /* multiqueue is disabled by default */ 725 vcrypto->curr_queues = 1; 726 if (!vcrypto->cryptodev->ready) { 727 vcrypto->status &= ~VIRTIO_CRYPTO_S_HW_READY; 728 } else { 729 vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY; 730 } 731 } 732 733 static void virtio_crypto_init_config(VirtIODevice *vdev) 734 { 735 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev); 736 737 vcrypto->conf.crypto_services = 738 vcrypto->conf.cryptodev->conf.crypto_services; 739 vcrypto->conf.cipher_algo_l = 740 vcrypto->conf.cryptodev->conf.cipher_algo_l; 741 vcrypto->conf.cipher_algo_h = 742 vcrypto->conf.cryptodev->conf.cipher_algo_h; 743 vcrypto->conf.hash_algo = vcrypto->conf.cryptodev->conf.hash_algo; 744 vcrypto->conf.mac_algo_l = vcrypto->conf.cryptodev->conf.mac_algo_l; 745 vcrypto->conf.mac_algo_h = vcrypto->conf.cryptodev->conf.mac_algo_h; 746 vcrypto->conf.aead_algo = vcrypto->conf.cryptodev->conf.aead_algo; 747 vcrypto->conf.max_cipher_key_len = 748 vcrypto->conf.cryptodev->conf.max_cipher_key_len; 749 vcrypto->conf.max_auth_key_len = 750 vcrypto->conf.cryptodev->conf.max_auth_key_len; 751 vcrypto->conf.max_size = vcrypto->conf.cryptodev->conf.max_size; 752 } 753 754 static void virtio_crypto_device_realize(DeviceState *dev, Error **errp) 755 { 756 VirtIODevice *vdev = VIRTIO_DEVICE(dev); 757 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev); 758 int i; 759 760 vcrypto->cryptodev = vcrypto->conf.cryptodev; 761 if (vcrypto->cryptodev == NULL) { 762 error_setg(errp, "'cryptodev' parameter expects a valid object"); 763 return; 764 } 765 766 vcrypto->max_queues = MAX(vcrypto->cryptodev->conf.peers.queues, 1); 767 if (vcrypto->max_queues + 1 > VIRTIO_QUEUE_MAX) { 768 error_setg(errp, "Invalid number of queues (= %" PRIu32 "), " 769 "must be a postive integer less than %d.", 770 vcrypto->max_queues, VIRTIO_QUEUE_MAX); 771 return; 772 } 773 774 virtio_init(vdev, "virtio-crypto", VIRTIO_ID_CRYPTO, vcrypto->config_size); 775 vcrypto->curr_queues = 1; 776 vcrypto->vqs = g_malloc0(sizeof(VirtIOCryptoQueue) * vcrypto->max_queues); 777 for (i = 0; i < vcrypto->max_queues; i++) { 778 vcrypto->vqs[i].dataq = 779 virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh); 780 vcrypto->vqs[i].dataq_bh = 781 qemu_bh_new(virtio_crypto_dataq_bh, &vcrypto->vqs[i]); 782 vcrypto->vqs[i].vcrypto = vcrypto; 783 } 784 785 vcrypto->ctrl_vq = virtio_add_queue(vdev, 64, virtio_crypto_handle_ctrl); 786 if (!vcrypto->cryptodev->ready) { 787 vcrypto->status &= ~VIRTIO_CRYPTO_S_HW_READY; 788 } else { 789 vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY; 790 } 791 792 virtio_crypto_init_config(vdev); 793 } 794 795 static void virtio_crypto_device_unrealize(DeviceState *dev, Error **errp) 796 { 797 VirtIODevice *vdev = VIRTIO_DEVICE(dev); 798 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev); 799 VirtIOCryptoQueue *q; 800 int i, max_queues; 801 802 max_queues = vcrypto->multiqueue ? vcrypto->max_queues : 1; 803 for (i = 0; i < max_queues; i++) { 804 virtio_del_queue(vdev, i); 805 q = &vcrypto->vqs[i]; 806 qemu_bh_delete(q->dataq_bh); 807 } 808 809 g_free(vcrypto->vqs); 810 811 virtio_cleanup(vdev); 812 } 813 814 static const VMStateDescription vmstate_virtio_crypto = { 815 .name = "virtio-crypto", 816 .unmigratable = 1, 817 .minimum_version_id = VIRTIO_CRYPTO_VM_VERSION, 818 .version_id = VIRTIO_CRYPTO_VM_VERSION, 819 .fields = (VMStateField[]) { 820 VMSTATE_VIRTIO_DEVICE, 821 VMSTATE_END_OF_LIST() 822 }, 823 }; 824 825 static Property virtio_crypto_properties[] = { 826 DEFINE_PROP_END_OF_LIST(), 827 }; 828 829 static void virtio_crypto_get_config(VirtIODevice *vdev, uint8_t *config) 830 { 831 VirtIOCrypto *c = VIRTIO_CRYPTO(vdev); 832 struct virtio_crypto_config crypto_cfg; 833 834 /* 835 * Virtio-crypto device conforms to VIRTIO 1.0 which is always LE, 836 * so we can use LE accessors directly. 837 */ 838 stl_le_p(&crypto_cfg.status, c->status); 839 stl_le_p(&crypto_cfg.max_dataqueues, c->max_queues); 840 stl_le_p(&crypto_cfg.crypto_services, c->conf.crypto_services); 841 stl_le_p(&crypto_cfg.cipher_algo_l, c->conf.cipher_algo_l); 842 stl_le_p(&crypto_cfg.cipher_algo_h, c->conf.cipher_algo_h); 843 stl_le_p(&crypto_cfg.hash_algo, c->conf.hash_algo); 844 stl_le_p(&crypto_cfg.mac_algo_l, c->conf.mac_algo_l); 845 stl_le_p(&crypto_cfg.mac_algo_h, c->conf.mac_algo_h); 846 stl_le_p(&crypto_cfg.aead_algo, c->conf.aead_algo); 847 stl_le_p(&crypto_cfg.max_cipher_key_len, c->conf.max_cipher_key_len); 848 stl_le_p(&crypto_cfg.max_auth_key_len, c->conf.max_auth_key_len); 849 stq_le_p(&crypto_cfg.max_size, c->conf.max_size); 850 851 memcpy(config, &crypto_cfg, c->config_size); 852 } 853 854 static void virtio_crypto_class_init(ObjectClass *klass, void *data) 855 { 856 DeviceClass *dc = DEVICE_CLASS(klass); 857 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); 858 859 dc->props = virtio_crypto_properties; 860 dc->vmsd = &vmstate_virtio_crypto; 861 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 862 vdc->realize = virtio_crypto_device_realize; 863 vdc->unrealize = virtio_crypto_device_unrealize; 864 vdc->get_config = virtio_crypto_get_config; 865 vdc->get_features = virtio_crypto_get_features; 866 vdc->reset = virtio_crypto_reset; 867 } 868 869 static void virtio_crypto_instance_init(Object *obj) 870 { 871 VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(obj); 872 873 /* 874 * The default config_size is sizeof(struct virtio_crypto_config). 875 * Can be overriden with virtio_crypto_set_config_size. 876 */ 877 vcrypto->config_size = sizeof(struct virtio_crypto_config); 878 879 object_property_add_link(obj, "cryptodev", 880 TYPE_CRYPTODEV_BACKEND, 881 (Object **)&vcrypto->conf.cryptodev, 882 qdev_prop_allow_set_link_before_realize, 883 OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL); 884 } 885 886 static const TypeInfo virtio_crypto_info = { 887 .name = TYPE_VIRTIO_CRYPTO, 888 .parent = TYPE_VIRTIO_DEVICE, 889 .instance_size = sizeof(VirtIOCrypto), 890 .instance_init = virtio_crypto_instance_init, 891 .class_init = virtio_crypto_class_init, 892 }; 893 894 static void virtio_register_types(void) 895 { 896 type_register_static(&virtio_crypto_info); 897 } 898 899 type_init(virtio_register_types) 900