xref: /qemu/hw/virtio/virtio-crypto.c (revision c7b64948)
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 
14 #include "qemu/osdep.h"
15 #include "qemu/iov.h"
16 #include "qemu/main-loop.h"
17 #include "qemu/module.h"
18 #include "qapi/error.h"
19 #include "qemu/error-report.h"
20 
21 #include "hw/virtio/virtio.h"
22 #include "hw/virtio/virtio-crypto.h"
23 #include "hw/qdev-properties.h"
24 #include "hw/virtio/virtio-access.h"
25 #include "standard-headers/linux/virtio_ids.h"
26 #include "sysemu/cryptodev-vhost.h"
27 
28 #define VIRTIO_CRYPTO_VM_VERSION 1
29 
30 typedef struct VirtIOCryptoSessionReq {
31     VirtIODevice *vdev;
32     VirtQueue *vq;
33     VirtQueueElement *elem;
34     CryptoDevBackendSessionInfo info;
35     CryptoDevCompletionFunc cb;
36 } VirtIOCryptoSessionReq;
37 
38 static void virtio_crypto_free_create_session_req(VirtIOCryptoSessionReq *sreq)
39 {
40     switch (sreq->info.op_code) {
41     case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
42         g_free(sreq->info.u.sym_sess_info.cipher_key);
43         g_free(sreq->info.u.sym_sess_info.auth_key);
44         break;
45 
46     case VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION:
47         g_free(sreq->info.u.asym_sess_info.key);
48         break;
49 
50     case VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION:
51     case VIRTIO_CRYPTO_HASH_DESTROY_SESSION:
52     case VIRTIO_CRYPTO_MAC_DESTROY_SESSION:
53     case VIRTIO_CRYPTO_AEAD_DESTROY_SESSION:
54     case VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION:
55         break;
56 
57     default:
58         error_report("Unknown opcode: %u", sreq->info.op_code);
59     }
60     g_free(sreq);
61 }
62 
63 /*
64  * Transfer virtqueue index to crypto queue index.
65  * The control virtqueue is after the data virtqueues
66  * so the input value doesn't need to be adjusted
67  */
68 static inline int virtio_crypto_vq2q(int queue_index)
69 {
70     return queue_index;
71 }
72 
73 static int
74 virtio_crypto_cipher_session_helper(VirtIODevice *vdev,
75            CryptoDevBackendSymSessionInfo *info,
76            struct virtio_crypto_cipher_session_para *cipher_para,
77            struct iovec **iov, unsigned int *out_num)
78 {
79     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
80     unsigned int num = *out_num;
81 
82     info->cipher_alg = ldl_le_p(&cipher_para->algo);
83     info->key_len = ldl_le_p(&cipher_para->keylen);
84     info->direction = ldl_le_p(&cipher_para->op);
85     DPRINTF("cipher_alg=%" PRIu32 ", info->direction=%" PRIu32 "\n",
86              info->cipher_alg, info->direction);
87 
88     if (info->key_len > vcrypto->conf.max_cipher_key_len) {
89         error_report("virtio-crypto length of cipher key is too big: %u",
90                      info->key_len);
91         return -VIRTIO_CRYPTO_ERR;
92     }
93     /* Get cipher key */
94     if (info->key_len > 0) {
95         size_t s;
96         DPRINTF("keylen=%" PRIu32 "\n", info->key_len);
97 
98         info->cipher_key = g_malloc(info->key_len);
99         s = iov_to_buf(*iov, num, 0, info->cipher_key, info->key_len);
100         if (unlikely(s != info->key_len)) {
101             virtio_error(vdev, "virtio-crypto cipher key incorrect");
102             return -EFAULT;
103         }
104         iov_discard_front(iov, &num, info->key_len);
105         *out_num = num;
106     }
107 
108     return 0;
109 }
110 
111 static int
112 virtio_crypto_create_sym_session(VirtIOCrypto *vcrypto,
113                struct virtio_crypto_sym_create_session_req *sess_req,
114                uint32_t queue_id,
115                uint32_t opcode,
116                struct iovec *iov, unsigned int out_num,
117                VirtIOCryptoSessionReq *sreq)
118 {
119     VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
120     CryptoDevBackendSymSessionInfo *sym_info = &sreq->info.u.sym_sess_info;
121     int queue_index;
122     uint32_t op_type;
123     int ret;
124 
125     op_type = ldl_le_p(&sess_req->op_type);
126     sreq->info.op_code = opcode;
127 
128     sym_info = &sreq->info.u.sym_sess_info;
129     sym_info->op_type = op_type;
130 
131     if (op_type == VIRTIO_CRYPTO_SYM_OP_CIPHER) {
132         ret = virtio_crypto_cipher_session_helper(vdev, sym_info,
133                            &sess_req->u.cipher.para,
134                            &iov, &out_num);
135         if (ret < 0) {
136             return ret;
137         }
138     } else if (op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
139         size_t s;
140         /* cipher part */
141         ret = virtio_crypto_cipher_session_helper(vdev, sym_info,
142                            &sess_req->u.chain.para.cipher_param,
143                            &iov, &out_num);
144         if (ret < 0) {
145             return ret;
146         }
147         /* hash part */
148         sym_info->alg_chain_order = ldl_le_p(
149                                      &sess_req->u.chain.para.alg_chain_order);
150         sym_info->add_len = ldl_le_p(&sess_req->u.chain.para.aad_len);
151         sym_info->hash_mode = ldl_le_p(&sess_req->u.chain.para.hash_mode);
152         if (sym_info->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH) {
153             sym_info->hash_alg =
154                 ldl_le_p(&sess_req->u.chain.para.u.mac_param.algo);
155             sym_info->auth_key_len = ldl_le_p(
156                              &sess_req->u.chain.para.u.mac_param.auth_key_len);
157             sym_info->hash_result_len = ldl_le_p(
158                            &sess_req->u.chain.para.u.mac_param.hash_result_len);
159             if (sym_info->auth_key_len > vcrypto->conf.max_auth_key_len) {
160                 error_report("virtio-crypto length of auth key is too big: %u",
161                              sym_info->auth_key_len);
162                 return -VIRTIO_CRYPTO_ERR;
163             }
164             /* get auth key */
165             if (sym_info->auth_key_len > 0) {
166                 sym_info->auth_key = g_malloc(sym_info->auth_key_len);
167                 s = iov_to_buf(iov, out_num, 0, sym_info->auth_key,
168                                sym_info->auth_key_len);
169                 if (unlikely(s != sym_info->auth_key_len)) {
170                     virtio_error(vdev,
171                           "virtio-crypto authenticated key incorrect");
172                     return -EFAULT;
173                 }
174                 iov_discard_front(&iov, &out_num, sym_info->auth_key_len);
175             }
176         } else if (sym_info->hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN) {
177             sym_info->hash_alg = ldl_le_p(
178                              &sess_req->u.chain.para.u.hash_param.algo);
179             sym_info->hash_result_len = ldl_le_p(
180                         &sess_req->u.chain.para.u.hash_param.hash_result_len);
181         } else {
182             /* VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED */
183             error_report("unsupported hash mode");
184             return -VIRTIO_CRYPTO_NOTSUPP;
185         }
186     } else {
187         /* VIRTIO_CRYPTO_SYM_OP_NONE */
188         error_report("unsupported cipher op_type: VIRTIO_CRYPTO_SYM_OP_NONE");
189         return -VIRTIO_CRYPTO_NOTSUPP;
190     }
191 
192     queue_index = virtio_crypto_vq2q(queue_id);
193     return cryptodev_backend_create_session(vcrypto->cryptodev, &sreq->info,
194                                             queue_index, sreq->cb, sreq);
195 }
196 
197 static int
198 virtio_crypto_create_asym_session(VirtIOCrypto *vcrypto,
199                struct virtio_crypto_akcipher_create_session_req *sess_req,
200                uint32_t queue_id, uint32_t opcode,
201                struct iovec *iov, unsigned int out_num,
202                VirtIOCryptoSessionReq *sreq)
203 {
204     VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
205     CryptoDevBackendAsymSessionInfo *asym_info = &sreq->info.u.asym_sess_info;
206     int queue_index;
207     uint32_t algo, keytype, keylen;
208 
209     algo = ldl_le_p(&sess_req->para.algo);
210     keytype = ldl_le_p(&sess_req->para.keytype);
211     keylen = ldl_le_p(&sess_req->para.keylen);
212 
213     if ((keytype != VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC)
214          && (keytype != VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE)) {
215         error_report("unsupported asym keytype: %d", keytype);
216         return -VIRTIO_CRYPTO_NOTSUPP;
217     }
218 
219     if (keylen) {
220         asym_info->key = g_malloc(keylen);
221         if (iov_to_buf(iov, out_num, 0, asym_info->key, keylen) != keylen) {
222             virtio_error(vdev, "virtio-crypto asym key incorrect");
223             return -EFAULT;
224         }
225         iov_discard_front(&iov, &out_num, keylen);
226     }
227 
228     sreq->info.op_code = opcode;
229     asym_info = &sreq->info.u.asym_sess_info;
230     asym_info->algo = algo;
231     asym_info->keytype = keytype;
232     asym_info->keylen = keylen;
233     switch (asym_info->algo) {
234     case VIRTIO_CRYPTO_AKCIPHER_RSA:
235         asym_info->u.rsa.padding_algo =
236             ldl_le_p(&sess_req->para.u.rsa.padding_algo);
237         asym_info->u.rsa.hash_algo =
238             ldl_le_p(&sess_req->para.u.rsa.hash_algo);
239         break;
240 
241     /* TODO DSA&ECDSA handling */
242 
243     default:
244         return -VIRTIO_CRYPTO_ERR;
245     }
246 
247     queue_index = virtio_crypto_vq2q(queue_id);
248     return cryptodev_backend_create_session(vcrypto->cryptodev, &sreq->info,
249                                             queue_index, sreq->cb, sreq);
250 }
251 
252 static int
253 virtio_crypto_handle_close_session(VirtIOCrypto *vcrypto,
254          struct virtio_crypto_destroy_session_req *close_sess_req,
255          uint32_t queue_id,
256          VirtIOCryptoSessionReq *sreq)
257 {
258     uint64_t session_id;
259 
260     session_id = ldq_le_p(&close_sess_req->session_id);
261     DPRINTF("close session, id=%" PRIu64 "\n", session_id);
262 
263     return cryptodev_backend_close_session(
264                 vcrypto->cryptodev, session_id, queue_id, sreq->cb, sreq);
265 }
266 
267 static void virtio_crypto_create_session_completion(void *opaque, int ret)
268 {
269     VirtIOCryptoSessionReq *sreq = (VirtIOCryptoSessionReq *)opaque;
270     VirtQueue *vq = sreq->vq;
271     VirtQueueElement *elem = sreq->elem;
272     VirtIODevice *vdev = sreq->vdev;
273     struct virtio_crypto_session_input input;
274     struct iovec *in_iov = elem->in_sg;
275     unsigned in_num = elem->in_num;
276     size_t s;
277 
278     memset(&input, 0, sizeof(input));
279     /* Serious errors, need to reset virtio crypto device */
280     if (ret == -EFAULT) {
281         virtqueue_detach_element(vq, elem, 0);
282         goto out;
283     } else if (ret == -VIRTIO_CRYPTO_NOTSUPP) {
284         stl_le_p(&input.status, VIRTIO_CRYPTO_NOTSUPP);
285     } else if (ret == -VIRTIO_CRYPTO_KEY_REJECTED) {
286         stl_le_p(&input.status, VIRTIO_CRYPTO_KEY_REJECTED);
287     } else if (ret != VIRTIO_CRYPTO_OK) {
288         stl_le_p(&input.status, VIRTIO_CRYPTO_ERR);
289     } else {
290         /* Set the session id */
291         stq_le_p(&input.session_id, sreq->info.session_id);
292         stl_le_p(&input.status, VIRTIO_CRYPTO_OK);
293     }
294 
295     s = iov_from_buf(in_iov, in_num, 0, &input, sizeof(input));
296     if (unlikely(s != sizeof(input))) {
297         virtio_error(vdev, "virtio-crypto input incorrect");
298         virtqueue_detach_element(vq, elem, 0);
299         goto out;
300     }
301     virtqueue_push(vq, elem, sizeof(input));
302     virtio_notify(vdev, vq);
303 
304 out:
305     g_free(elem);
306     virtio_crypto_free_create_session_req(sreq);
307 }
308 
309 static void virtio_crypto_destroy_session_completion(void *opaque, int ret)
310 {
311     VirtIOCryptoSessionReq *sreq = (VirtIOCryptoSessionReq *)opaque;
312     VirtQueue *vq = sreq->vq;
313     VirtQueueElement *elem = sreq->elem;
314     VirtIODevice *vdev = sreq->vdev;
315     struct iovec *in_iov = elem->in_sg;
316     unsigned in_num = elem->in_num;
317     uint8_t status;
318     size_t s;
319 
320     if (ret < 0) {
321         status = VIRTIO_CRYPTO_ERR;
322     } else {
323         status = VIRTIO_CRYPTO_OK;
324     }
325     s = iov_from_buf(in_iov, in_num, 0, &status, sizeof(status));
326     if (unlikely(s != sizeof(status))) {
327         virtio_error(vdev, "virtio-crypto status incorrect");
328         virtqueue_detach_element(vq, elem, 0);
329         goto out;
330     }
331     virtqueue_push(vq, elem, sizeof(status));
332     virtio_notify(vdev, vq);
333 
334 out:
335     g_free(elem);
336     g_free(sreq);
337 }
338 
339 static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
340 {
341     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
342     struct virtio_crypto_op_ctrl_req ctrl;
343     VirtQueueElement *elem;
344     VirtIOCryptoSessionReq *sreq;
345     unsigned out_num;
346     unsigned in_num;
347     uint32_t queue_id;
348     uint32_t opcode;
349     struct virtio_crypto_session_input input;
350     size_t s;
351     int ret;
352     struct iovec *out_iov;
353     struct iovec *in_iov;
354 
355     for (;;) {
356         g_autofree struct iovec *out_iov_copy = NULL;
357 
358         elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
359         if (!elem) {
360             break;
361         }
362         if (elem->out_num < 1 || elem->in_num < 1) {
363             virtio_error(vdev, "virtio-crypto ctrl missing headers");
364             virtqueue_detach_element(vq, elem, 0);
365             g_free(elem);
366             break;
367         }
368 
369         out_num = elem->out_num;
370         out_iov_copy = g_memdup2(elem->out_sg, sizeof(out_iov[0]) * out_num);
371         out_iov = out_iov_copy;
372 
373         in_num = elem->in_num;
374         in_iov = elem->in_sg;
375 
376         if (unlikely(iov_to_buf(out_iov, out_num, 0, &ctrl, sizeof(ctrl))
377                     != sizeof(ctrl))) {
378             virtio_error(vdev, "virtio-crypto request ctrl_hdr too short");
379             virtqueue_detach_element(vq, elem, 0);
380             g_free(elem);
381             break;
382         }
383         iov_discard_front(&out_iov, &out_num, sizeof(ctrl));
384 
385         opcode = ldl_le_p(&ctrl.header.opcode);
386         queue_id = ldl_le_p(&ctrl.header.queue_id);
387 
388         sreq = g_new0(VirtIOCryptoSessionReq, 1);
389         sreq->vdev = vdev;
390         sreq->vq = vq;
391         sreq->elem = elem;
392 
393         switch (opcode) {
394         case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
395             sreq->cb = virtio_crypto_create_session_completion;
396             ret = virtio_crypto_create_sym_session(vcrypto,
397                             &ctrl.u.sym_create_session,
398                             queue_id, opcode,
399                             out_iov, out_num,
400                             sreq);
401             if (ret < 0) {
402                 virtio_crypto_create_session_completion(sreq, ret);
403             }
404             break;
405 
406         case VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION:
407             sreq->cb = virtio_crypto_create_session_completion;
408             ret = virtio_crypto_create_asym_session(vcrypto,
409                              &ctrl.u.akcipher_create_session,
410                              queue_id, opcode,
411                              out_iov, out_num,
412                              sreq);
413             if (ret < 0) {
414                 virtio_crypto_create_session_completion(sreq, ret);
415             }
416             break;
417 
418         case VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION:
419         case VIRTIO_CRYPTO_HASH_DESTROY_SESSION:
420         case VIRTIO_CRYPTO_MAC_DESTROY_SESSION:
421         case VIRTIO_CRYPTO_AEAD_DESTROY_SESSION:
422         case VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION:
423             sreq->cb = virtio_crypto_destroy_session_completion;
424             ret = virtio_crypto_handle_close_session(vcrypto,
425                    &ctrl.u.destroy_session, queue_id,
426                    sreq);
427             if (ret < 0) {
428                 virtio_crypto_destroy_session_completion(sreq, ret);
429             }
430             break;
431 
432         case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
433         case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
434         case VIRTIO_CRYPTO_AEAD_CREATE_SESSION:
435         default:
436             memset(&input, 0, sizeof(input));
437             error_report("virtio-crypto unsupported ctrl opcode: %d", opcode);
438             stl_le_p(&input.status, VIRTIO_CRYPTO_NOTSUPP);
439             s = iov_from_buf(in_iov, in_num, 0, &input, sizeof(input));
440             if (unlikely(s != sizeof(input))) {
441                 virtio_error(vdev, "virtio-crypto input incorrect");
442                 virtqueue_detach_element(vq, elem, 0);
443             } else {
444                 virtqueue_push(vq, elem, sizeof(input));
445                 virtio_notify(vdev, vq);
446             }
447             g_free(sreq);
448             g_free(elem);
449 
450             break;
451         } /* end switch case */
452 
453     } /* end for loop */
454 }
455 
456 static void virtio_crypto_init_request(VirtIOCrypto *vcrypto, VirtQueue *vq,
457                                 VirtIOCryptoReq *req)
458 {
459     req->vcrypto = vcrypto;
460     req->vq = vq;
461     req->in = NULL;
462     req->in_iov = NULL;
463     req->in_num = 0;
464     req->in_len = 0;
465     req->flags = QCRYPTODEV_BACKEND_ALG__MAX;
466     memset(&req->op_info, 0x00, sizeof(req->op_info));
467 }
468 
469 static void virtio_crypto_free_request(VirtIOCryptoReq *req)
470 {
471     if (!req) {
472         return;
473     }
474 
475     if (req->flags == QCRYPTODEV_BACKEND_ALG_SYM) {
476         size_t max_len;
477         CryptoDevBackendSymOpInfo *op_info = req->op_info.u.sym_op_info;
478 
479         if (op_info) {
480             max_len = op_info->iv_len +
481                       op_info->aad_len +
482                       op_info->src_len +
483                       op_info->dst_len +
484                       op_info->digest_result_len;
485 
486             /* Zeroize and free request data structure */
487             memset(op_info, 0, sizeof(*op_info) + max_len);
488             g_free(op_info);
489         }
490     } else if (req->flags == QCRYPTODEV_BACKEND_ALG_ASYM) {
491         CryptoDevBackendAsymOpInfo *op_info = req->op_info.u.asym_op_info;
492         if (op_info) {
493             g_free(op_info->src);
494             g_free(op_info->dst);
495             memset(op_info, 0, sizeof(*op_info));
496             g_free(op_info);
497         }
498     }
499 
500     g_free(req->in_iov);
501     g_free(req);
502 }
503 
504 static void
505 virtio_crypto_sym_input_data_helper(VirtIODevice *vdev,
506                 VirtIOCryptoReq *req,
507                 uint32_t status,
508                 CryptoDevBackendSymOpInfo *sym_op_info)
509 {
510     size_t s, len;
511     struct iovec *in_iov = req->in_iov;
512 
513     if (status != VIRTIO_CRYPTO_OK) {
514         return;
515     }
516 
517     len = sym_op_info->src_len;
518     /* Save the cipher result */
519     s = iov_from_buf(in_iov, req->in_num, 0, sym_op_info->dst, len);
520     if (s != len) {
521         virtio_error(vdev, "virtio-crypto dest data incorrect");
522         return;
523     }
524 
525     iov_discard_front(&in_iov, &req->in_num, len);
526 
527     if (sym_op_info->op_type ==
528                       VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
529         /* Save the digest result */
530         s = iov_from_buf(in_iov, req->in_num, 0,
531                          sym_op_info->digest_result,
532                          sym_op_info->digest_result_len);
533         if (s != sym_op_info->digest_result_len) {
534             virtio_error(vdev, "virtio-crypto digest result incorrect");
535         }
536     }
537 }
538 
539 static void
540 virtio_crypto_akcipher_input_data_helper(VirtIODevice *vdev,
541         VirtIOCryptoReq *req, int32_t status,
542         CryptoDevBackendAsymOpInfo *asym_op_info)
543 {
544     size_t s, len;
545     struct iovec *in_iov = req->in_iov;
546 
547     if (status != VIRTIO_CRYPTO_OK) {
548         return;
549     }
550 
551     len = asym_op_info->dst_len;
552     if (!len) {
553         return;
554     }
555 
556     s = iov_from_buf(in_iov, req->in_num, 0, asym_op_info->dst, len);
557     if (s != len) {
558         virtio_error(vdev, "virtio-crypto asym dest data incorrect");
559         return;
560     }
561 
562     iov_discard_front(&in_iov, &req->in_num, len);
563 
564     /* For akcipher, dst_len may be changed after operation */
565     req->in_len = sizeof(struct virtio_crypto_inhdr) + asym_op_info->dst_len;
566 }
567 
568 static void virtio_crypto_req_complete(void *opaque, int ret)
569 {
570     VirtIOCryptoReq *req = (VirtIOCryptoReq *)opaque;
571     VirtIOCrypto *vcrypto = req->vcrypto;
572     VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
573     uint8_t status = -ret;
574 
575     if (req->flags == QCRYPTODEV_BACKEND_ALG_SYM) {
576         virtio_crypto_sym_input_data_helper(vdev, req, status,
577                                             req->op_info.u.sym_op_info);
578     } else if (req->flags == QCRYPTODEV_BACKEND_ALG_ASYM) {
579         virtio_crypto_akcipher_input_data_helper(vdev, req, status,
580                                              req->op_info.u.asym_op_info);
581     }
582     stb_p(&req->in->status, status);
583     virtqueue_push(req->vq, &req->elem, req->in_len);
584     virtio_notify(vdev, req->vq);
585     virtio_crypto_free_request(req);
586 }
587 
588 static VirtIOCryptoReq *
589 virtio_crypto_get_request(VirtIOCrypto *s, VirtQueue *vq)
590 {
591     VirtIOCryptoReq *req = virtqueue_pop(vq, sizeof(VirtIOCryptoReq));
592 
593     if (req) {
594         virtio_crypto_init_request(s, vq, req);
595     }
596     return req;
597 }
598 
599 static CryptoDevBackendSymOpInfo *
600 virtio_crypto_sym_op_helper(VirtIODevice *vdev,
601            struct virtio_crypto_cipher_para *cipher_para,
602            struct virtio_crypto_alg_chain_data_para *alg_chain_para,
603            struct iovec *iov, unsigned int out_num)
604 {
605     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
606     CryptoDevBackendSymOpInfo *op_info;
607     uint32_t src_len = 0, dst_len = 0;
608     uint32_t iv_len = 0;
609     uint32_t aad_len = 0, hash_result_len = 0;
610     uint32_t hash_start_src_offset = 0, len_to_hash = 0;
611     uint32_t cipher_start_src_offset = 0, len_to_cipher = 0;
612 
613     uint64_t max_len, curr_size = 0;
614     size_t s;
615 
616     /* Plain cipher */
617     if (cipher_para) {
618         iv_len = ldl_le_p(&cipher_para->iv_len);
619         src_len = ldl_le_p(&cipher_para->src_data_len);
620         dst_len = ldl_le_p(&cipher_para->dst_data_len);
621     } else if (alg_chain_para) { /* Algorithm chain */
622         iv_len = ldl_le_p(&alg_chain_para->iv_len);
623         src_len = ldl_le_p(&alg_chain_para->src_data_len);
624         dst_len = ldl_le_p(&alg_chain_para->dst_data_len);
625 
626         aad_len = ldl_le_p(&alg_chain_para->aad_len);
627         hash_result_len = ldl_le_p(&alg_chain_para->hash_result_len);
628         hash_start_src_offset = ldl_le_p(
629                          &alg_chain_para->hash_start_src_offset);
630         cipher_start_src_offset = ldl_le_p(
631                          &alg_chain_para->cipher_start_src_offset);
632         len_to_cipher = ldl_le_p(&alg_chain_para->len_to_cipher);
633         len_to_hash = ldl_le_p(&alg_chain_para->len_to_hash);
634     } else {
635         return NULL;
636     }
637 
638     max_len = (uint64_t)iv_len + aad_len + src_len + dst_len + hash_result_len;
639     if (unlikely(max_len > vcrypto->conf.max_size)) {
640         virtio_error(vdev, "virtio-crypto too big length");
641         return NULL;
642     }
643 
644     op_info = g_malloc0(sizeof(CryptoDevBackendSymOpInfo) + max_len);
645     op_info->iv_len = iv_len;
646     op_info->src_len = src_len;
647     op_info->dst_len = dst_len;
648     op_info->aad_len = aad_len;
649     op_info->digest_result_len = hash_result_len;
650     op_info->hash_start_src_offset = hash_start_src_offset;
651     op_info->len_to_hash = len_to_hash;
652     op_info->cipher_start_src_offset = cipher_start_src_offset;
653     op_info->len_to_cipher = len_to_cipher;
654     /* Handle the initilization vector */
655     if (op_info->iv_len > 0) {
656         DPRINTF("iv_len=%" PRIu32 "\n", op_info->iv_len);
657         op_info->iv = op_info->data + curr_size;
658 
659         s = iov_to_buf(iov, out_num, 0, op_info->iv, op_info->iv_len);
660         if (unlikely(s != op_info->iv_len)) {
661             virtio_error(vdev, "virtio-crypto iv incorrect");
662             goto err;
663         }
664         iov_discard_front(&iov, &out_num, op_info->iv_len);
665         curr_size += op_info->iv_len;
666     }
667 
668     /* Handle additional authentication data if exists */
669     if (op_info->aad_len > 0) {
670         DPRINTF("aad_len=%" PRIu32 "\n", op_info->aad_len);
671         op_info->aad_data = op_info->data + curr_size;
672 
673         s = iov_to_buf(iov, out_num, 0, op_info->aad_data, op_info->aad_len);
674         if (unlikely(s != op_info->aad_len)) {
675             virtio_error(vdev, "virtio-crypto additional auth data incorrect");
676             goto err;
677         }
678         iov_discard_front(&iov, &out_num, op_info->aad_len);
679 
680         curr_size += op_info->aad_len;
681     }
682 
683     /* Handle the source data */
684     if (op_info->src_len > 0) {
685         DPRINTF("src_len=%" PRIu32 "\n", op_info->src_len);
686         op_info->src = op_info->data + curr_size;
687 
688         s = iov_to_buf(iov, out_num, 0, op_info->src, op_info->src_len);
689         if (unlikely(s != op_info->src_len)) {
690             virtio_error(vdev, "virtio-crypto source data incorrect");
691             goto err;
692         }
693         iov_discard_front(&iov, &out_num, op_info->src_len);
694 
695         curr_size += op_info->src_len;
696     }
697 
698     /* Handle the destination data */
699     op_info->dst = op_info->data + curr_size;
700     curr_size += op_info->dst_len;
701 
702     DPRINTF("dst_len=%" PRIu32 "\n", op_info->dst_len);
703 
704     /* Handle the hash digest result */
705     if (hash_result_len > 0) {
706         DPRINTF("hash_result_len=%" PRIu32 "\n", hash_result_len);
707         op_info->digest_result = op_info->data + curr_size;
708     }
709 
710     return op_info;
711 
712 err:
713     g_free(op_info);
714     return NULL;
715 }
716 
717 static int
718 virtio_crypto_handle_sym_req(VirtIOCrypto *vcrypto,
719                struct virtio_crypto_sym_data_req *req,
720                CryptoDevBackendOpInfo *op_info,
721                struct iovec *iov, unsigned int out_num)
722 {
723     VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
724     CryptoDevBackendSymOpInfo *sym_op_info;
725     uint32_t op_type;
726 
727     op_type = ldl_le_p(&req->op_type);
728     if (op_type == VIRTIO_CRYPTO_SYM_OP_CIPHER) {
729         sym_op_info = virtio_crypto_sym_op_helper(vdev, &req->u.cipher.para,
730                                               NULL, iov, out_num);
731         if (!sym_op_info) {
732             return -EFAULT;
733         }
734     } else if (op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
735         sym_op_info = virtio_crypto_sym_op_helper(vdev, NULL,
736                                               &req->u.chain.para,
737                                               iov, out_num);
738         if (!sym_op_info) {
739             return -EFAULT;
740         }
741     } else {
742         /* VIRTIO_CRYPTO_SYM_OP_NONE */
743         error_report("virtio-crypto unsupported cipher type");
744         return -VIRTIO_CRYPTO_NOTSUPP;
745     }
746 
747     sym_op_info->op_type = op_type;
748     op_info->u.sym_op_info = sym_op_info;
749 
750     return 0;
751 }
752 
753 static int
754 virtio_crypto_handle_asym_req(VirtIOCrypto *vcrypto,
755                struct virtio_crypto_akcipher_data_req *req,
756                CryptoDevBackendOpInfo *op_info,
757                struct iovec *iov, unsigned int out_num)
758 {
759     VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
760     CryptoDevBackendAsymOpInfo *asym_op_info;
761     uint32_t src_len;
762     uint32_t dst_len;
763     uint32_t len;
764     uint8_t *src = NULL;
765     uint8_t *dst = NULL;
766 
767     asym_op_info = g_new0(CryptoDevBackendAsymOpInfo, 1);
768     src_len = ldl_le_p(&req->para.src_data_len);
769     dst_len = ldl_le_p(&req->para.dst_data_len);
770 
771     if (src_len > 0) {
772         src = g_malloc0(src_len);
773         len = iov_to_buf(iov, out_num, 0, src, src_len);
774         if (unlikely(len != src_len)) {
775             virtio_error(vdev, "virtio-crypto asym src data incorrect"
776                          "expected %u, actual %u", src_len, len);
777             goto err;
778         }
779 
780         iov_discard_front(&iov, &out_num, src_len);
781     }
782 
783     if (dst_len > 0) {
784         dst = g_malloc0(dst_len);
785 
786         if (op_info->op_code == VIRTIO_CRYPTO_AKCIPHER_VERIFY) {
787             len = iov_to_buf(iov, out_num, 0, dst, dst_len);
788             if (unlikely(len != dst_len)) {
789                 virtio_error(vdev, "virtio-crypto asym dst data incorrect"
790                              "expected %u, actual %u", dst_len, len);
791                 goto err;
792             }
793 
794             iov_discard_front(&iov, &out_num, dst_len);
795         }
796     }
797 
798     asym_op_info->src_len = src_len;
799     asym_op_info->dst_len = dst_len;
800     asym_op_info->src = src;
801     asym_op_info->dst = dst;
802     op_info->u.asym_op_info = asym_op_info;
803 
804     return 0;
805 
806  err:
807     g_free(asym_op_info);
808     g_free(src);
809     g_free(dst);
810 
811     return -EFAULT;
812 }
813 
814 static int
815 virtio_crypto_handle_request(VirtIOCryptoReq *request)
816 {
817     VirtIOCrypto *vcrypto = request->vcrypto;
818     VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
819     VirtQueueElement *elem = &request->elem;
820     int queue_index = virtio_crypto_vq2q(virtio_get_queue_index(request->vq));
821     struct virtio_crypto_op_data_req req;
822     int ret;
823     g_autofree struct iovec *in_iov_copy = NULL;
824     g_autofree struct iovec *out_iov_copy = NULL;
825     struct iovec *in_iov;
826     struct iovec *out_iov;
827     unsigned in_num;
828     unsigned out_num;
829     uint32_t opcode;
830     CryptoDevBackendOpInfo *op_info = &request->op_info;
831 
832     if (elem->out_num < 1 || elem->in_num < 1) {
833         virtio_error(vdev, "virtio-crypto dataq missing headers");
834         return -1;
835     }
836 
837     out_num = elem->out_num;
838     out_iov_copy = g_memdup2(elem->out_sg, sizeof(out_iov[0]) * out_num);
839     out_iov = out_iov_copy;
840 
841     in_num = elem->in_num;
842     in_iov_copy = g_memdup2(elem->in_sg, sizeof(in_iov[0]) * in_num);
843     in_iov = in_iov_copy;
844 
845     if (unlikely(iov_to_buf(out_iov, out_num, 0, &req, sizeof(req))
846                 != sizeof(req))) {
847         virtio_error(vdev, "virtio-crypto request outhdr too short");
848         return -1;
849     }
850     iov_discard_front(&out_iov, &out_num, sizeof(req));
851 
852     if (in_iov[in_num - 1].iov_len <
853             sizeof(struct virtio_crypto_inhdr)) {
854         virtio_error(vdev, "virtio-crypto request inhdr too short");
855         return -1;
856     }
857     /* We always touch the last byte, so just see how big in_iov is. */
858     request->in_len = iov_size(in_iov, in_num);
859     request->in = (void *)in_iov[in_num - 1].iov_base
860               + in_iov[in_num - 1].iov_len
861               - sizeof(struct virtio_crypto_inhdr);
862     iov_discard_back(in_iov, &in_num, sizeof(struct virtio_crypto_inhdr));
863 
864     /*
865      * The length of operation result, including dest_data
866      * and digest_result if exists.
867      */
868     request->in_num = in_num;
869     request->in_iov = in_iov;
870     /* now, we free the in_iov_copy inside virtio_crypto_free_request */
871     in_iov_copy = NULL;
872 
873     opcode = ldl_le_p(&req.header.opcode);
874     op_info->session_id = ldq_le_p(&req.header.session_id);
875     op_info->op_code = opcode;
876     op_info->queue_index = queue_index;
877     op_info->cb = virtio_crypto_req_complete;
878     op_info->opaque = request;
879 
880     switch (opcode) {
881     case VIRTIO_CRYPTO_CIPHER_ENCRYPT:
882     case VIRTIO_CRYPTO_CIPHER_DECRYPT:
883         op_info->algtype = request->flags = QCRYPTODEV_BACKEND_ALG_SYM;
884         ret = virtio_crypto_handle_sym_req(vcrypto,
885                          &req.u.sym_req, op_info,
886                          out_iov, out_num);
887         goto check_result;
888 
889     case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
890     case VIRTIO_CRYPTO_AKCIPHER_DECRYPT:
891     case VIRTIO_CRYPTO_AKCIPHER_SIGN:
892     case VIRTIO_CRYPTO_AKCIPHER_VERIFY:
893         op_info->algtype = request->flags = QCRYPTODEV_BACKEND_ALG_ASYM;
894         ret = virtio_crypto_handle_asym_req(vcrypto,
895                          &req.u.akcipher_req, op_info,
896                          out_iov, out_num);
897 
898 check_result:
899         /* Serious errors, need to reset virtio crypto device */
900         if (ret == -EFAULT) {
901             return -1;
902         } else if (ret == -VIRTIO_CRYPTO_NOTSUPP) {
903             virtio_crypto_req_complete(request, -VIRTIO_CRYPTO_NOTSUPP);
904         } else {
905             ret = cryptodev_backend_crypto_operation(vcrypto->cryptodev,
906                                     op_info);
907             if (ret < 0) {
908                 virtio_crypto_req_complete(request, ret);
909             }
910         }
911         break;
912 
913     case VIRTIO_CRYPTO_HASH:
914     case VIRTIO_CRYPTO_MAC:
915     case VIRTIO_CRYPTO_AEAD_ENCRYPT:
916     case VIRTIO_CRYPTO_AEAD_DECRYPT:
917     default:
918         error_report("virtio-crypto unsupported dataq opcode: %u",
919                      opcode);
920         virtio_crypto_req_complete(request, -VIRTIO_CRYPTO_NOTSUPP);
921     }
922 
923     return 0;
924 }
925 
926 static void virtio_crypto_handle_dataq(VirtIODevice *vdev, VirtQueue *vq)
927 {
928     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
929     VirtIOCryptoReq *req;
930 
931     while ((req = virtio_crypto_get_request(vcrypto, vq))) {
932         if (virtio_crypto_handle_request(req) < 0) {
933             virtqueue_detach_element(req->vq, &req->elem, 0);
934             virtio_crypto_free_request(req);
935             break;
936         }
937     }
938 }
939 
940 static void virtio_crypto_dataq_bh(void *opaque)
941 {
942     VirtIOCryptoQueue *q = opaque;
943     VirtIOCrypto *vcrypto = q->vcrypto;
944     VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
945 
946     /* This happens when device was stopped but BH wasn't. */
947     if (!vdev->vm_running) {
948         return;
949     }
950 
951     /* Just in case the driver is not ready on more */
952     if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) {
953         return;
954     }
955 
956     for (;;) {
957         virtio_crypto_handle_dataq(vdev, q->dataq);
958         virtio_queue_set_notification(q->dataq, 1);
959 
960         /* Are we done or did the guest add more buffers? */
961         if (virtio_queue_empty(q->dataq)) {
962             break;
963         }
964 
965         virtio_queue_set_notification(q->dataq, 0);
966     }
967 }
968 
969 static void
970 virtio_crypto_handle_dataq_bh(VirtIODevice *vdev, VirtQueue *vq)
971 {
972     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
973     VirtIOCryptoQueue *q =
974          &vcrypto->vqs[virtio_crypto_vq2q(virtio_get_queue_index(vq))];
975 
976     /* This happens when device was stopped but VCPU wasn't. */
977     if (!vdev->vm_running) {
978         return;
979     }
980     virtio_queue_set_notification(vq, 0);
981     qemu_bh_schedule(q->dataq_bh);
982 }
983 
984 static uint64_t virtio_crypto_get_features(VirtIODevice *vdev,
985                                            uint64_t features,
986                                            Error **errp)
987 {
988     return features;
989 }
990 
991 static void virtio_crypto_reset(VirtIODevice *vdev)
992 {
993     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
994     /* multiqueue is disabled by default */
995     vcrypto->curr_queues = 1;
996     if (!cryptodev_backend_is_ready(vcrypto->cryptodev)) {
997         vcrypto->status &= ~VIRTIO_CRYPTO_S_HW_READY;
998     } else {
999         vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY;
1000     }
1001 }
1002 
1003 static uint32_t virtio_crypto_init_services(uint32_t qservices)
1004 {
1005     uint32_t vservices = 0;
1006 
1007     if (qservices & (1 << QCRYPTODEV_BACKEND_SERVICE_CIPHER)) {
1008         vservices |= (1 << VIRTIO_CRYPTO_SERVICE_CIPHER);
1009     }
1010     if (qservices & (1 << QCRYPTODEV_BACKEND_SERVICE_HASH)) {
1011         vservices |= (1 << VIRTIO_CRYPTO_SERVICE_HASH);
1012     }
1013     if (qservices & (1 << QCRYPTODEV_BACKEND_SERVICE_MAC)) {
1014         vservices |= (1 << VIRTIO_CRYPTO_SERVICE_MAC);
1015     }
1016     if (qservices & (1 << QCRYPTODEV_BACKEND_SERVICE_AEAD)) {
1017         vservices |= (1 << VIRTIO_CRYPTO_SERVICE_AEAD);
1018     }
1019     if (qservices & (1 << QCRYPTODEV_BACKEND_SERVICE_AKCIPHER)) {
1020         vservices |= (1 << VIRTIO_CRYPTO_SERVICE_AKCIPHER);
1021     }
1022 
1023     return vservices;
1024 }
1025 
1026 static void virtio_crypto_init_config(VirtIODevice *vdev)
1027 {
1028     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
1029 
1030     vcrypto->conf.crypto_services = virtio_crypto_init_services(
1031                      vcrypto->conf.cryptodev->conf.crypto_services);
1032     vcrypto->conf.cipher_algo_l =
1033                      vcrypto->conf.cryptodev->conf.cipher_algo_l;
1034     vcrypto->conf.cipher_algo_h =
1035                      vcrypto->conf.cryptodev->conf.cipher_algo_h;
1036     vcrypto->conf.hash_algo = vcrypto->conf.cryptodev->conf.hash_algo;
1037     vcrypto->conf.mac_algo_l = vcrypto->conf.cryptodev->conf.mac_algo_l;
1038     vcrypto->conf.mac_algo_h = vcrypto->conf.cryptodev->conf.mac_algo_h;
1039     vcrypto->conf.aead_algo = vcrypto->conf.cryptodev->conf.aead_algo;
1040     vcrypto->conf.akcipher_algo = vcrypto->conf.cryptodev->conf.akcipher_algo;
1041     vcrypto->conf.max_cipher_key_len =
1042                   vcrypto->conf.cryptodev->conf.max_cipher_key_len;
1043     vcrypto->conf.max_auth_key_len =
1044                   vcrypto->conf.cryptodev->conf.max_auth_key_len;
1045     vcrypto->conf.max_size = vcrypto->conf.cryptodev->conf.max_size;
1046 }
1047 
1048 static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
1049 {
1050     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1051     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
1052     int i;
1053 
1054     vcrypto->cryptodev = vcrypto->conf.cryptodev;
1055     if (vcrypto->cryptodev == NULL) {
1056         error_setg(errp, "'cryptodev' parameter expects a valid object");
1057         return;
1058     } else if (cryptodev_backend_is_used(vcrypto->cryptodev)) {
1059         error_setg(errp, "can't use already used cryptodev backend: %s",
1060                    object_get_canonical_path_component(OBJECT(vcrypto->conf.cryptodev)));
1061         return;
1062     }
1063 
1064     vcrypto->max_queues = MAX(vcrypto->cryptodev->conf.peers.queues, 1);
1065     if (vcrypto->max_queues + 1 > VIRTIO_QUEUE_MAX) {
1066         error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
1067                    "must be a positive integer less than %d.",
1068                    vcrypto->max_queues, VIRTIO_QUEUE_MAX);
1069         return;
1070     }
1071 
1072     virtio_init(vdev, VIRTIO_ID_CRYPTO, vcrypto->config_size);
1073     vcrypto->curr_queues = 1;
1074     vcrypto->vqs = g_new0(VirtIOCryptoQueue, vcrypto->max_queues);
1075     for (i = 0; i < vcrypto->max_queues; i++) {
1076         vcrypto->vqs[i].dataq =
1077                  virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq_bh);
1078         vcrypto->vqs[i].dataq_bh =
1079                  qemu_bh_new_guarded(virtio_crypto_dataq_bh, &vcrypto->vqs[i],
1080                                      &dev->mem_reentrancy_guard);
1081         vcrypto->vqs[i].vcrypto = vcrypto;
1082     }
1083 
1084     vcrypto->ctrl_vq = virtio_add_queue(vdev, 1024, virtio_crypto_handle_ctrl);
1085     if (!cryptodev_backend_is_ready(vcrypto->cryptodev)) {
1086         vcrypto->status &= ~VIRTIO_CRYPTO_S_HW_READY;
1087     } else {
1088         vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY;
1089     }
1090 
1091     virtio_crypto_init_config(vdev);
1092     cryptodev_backend_set_used(vcrypto->cryptodev, true);
1093 }
1094 
1095 static void virtio_crypto_device_unrealize(DeviceState *dev)
1096 {
1097     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1098     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
1099     VirtIOCryptoQueue *q;
1100     int i, max_queues;
1101 
1102     max_queues = vcrypto->multiqueue ? vcrypto->max_queues : 1;
1103     for (i = 0; i < max_queues; i++) {
1104         virtio_delete_queue(vcrypto->vqs[i].dataq);
1105         q = &vcrypto->vqs[i];
1106         qemu_bh_delete(q->dataq_bh);
1107     }
1108 
1109     g_free(vcrypto->vqs);
1110     virtio_delete_queue(vcrypto->ctrl_vq);
1111 
1112     virtio_cleanup(vdev);
1113     cryptodev_backend_set_used(vcrypto->cryptodev, false);
1114 }
1115 
1116 static const VMStateDescription vmstate_virtio_crypto = {
1117     .name = "virtio-crypto",
1118     .unmigratable = 1,
1119     .minimum_version_id = VIRTIO_CRYPTO_VM_VERSION,
1120     .version_id = VIRTIO_CRYPTO_VM_VERSION,
1121     .fields = (VMStateField[]) {
1122         VMSTATE_VIRTIO_DEVICE,
1123         VMSTATE_END_OF_LIST()
1124     },
1125 };
1126 
1127 static Property virtio_crypto_properties[] = {
1128     DEFINE_PROP_LINK("cryptodev", VirtIOCrypto, conf.cryptodev,
1129                      TYPE_CRYPTODEV_BACKEND, CryptoDevBackend *),
1130     DEFINE_PROP_END_OF_LIST(),
1131 };
1132 
1133 static void virtio_crypto_get_config(VirtIODevice *vdev, uint8_t *config)
1134 {
1135     VirtIOCrypto *c = VIRTIO_CRYPTO(vdev);
1136     struct virtio_crypto_config crypto_cfg = {};
1137 
1138     /*
1139      * Virtio-crypto device conforms to VIRTIO 1.0 which is always LE,
1140      * so we can use LE accessors directly.
1141      */
1142     stl_le_p(&crypto_cfg.status, c->status);
1143     stl_le_p(&crypto_cfg.max_dataqueues, c->max_queues);
1144     stl_le_p(&crypto_cfg.crypto_services, c->conf.crypto_services);
1145     stl_le_p(&crypto_cfg.cipher_algo_l, c->conf.cipher_algo_l);
1146     stl_le_p(&crypto_cfg.cipher_algo_h, c->conf.cipher_algo_h);
1147     stl_le_p(&crypto_cfg.hash_algo, c->conf.hash_algo);
1148     stl_le_p(&crypto_cfg.mac_algo_l, c->conf.mac_algo_l);
1149     stl_le_p(&crypto_cfg.mac_algo_h, c->conf.mac_algo_h);
1150     stl_le_p(&crypto_cfg.aead_algo, c->conf.aead_algo);
1151     stl_le_p(&crypto_cfg.max_cipher_key_len, c->conf.max_cipher_key_len);
1152     stl_le_p(&crypto_cfg.max_auth_key_len, c->conf.max_auth_key_len);
1153     stq_le_p(&crypto_cfg.max_size, c->conf.max_size);
1154     stl_le_p(&crypto_cfg.akcipher_algo, c->conf.akcipher_algo);
1155 
1156     memcpy(config, &crypto_cfg, c->config_size);
1157 }
1158 
1159 static bool virtio_crypto_started(VirtIOCrypto *c, uint8_t status)
1160 {
1161     VirtIODevice *vdev = VIRTIO_DEVICE(c);
1162     return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
1163         (c->status & VIRTIO_CRYPTO_S_HW_READY) && vdev->vm_running;
1164 }
1165 
1166 static void virtio_crypto_vhost_status(VirtIOCrypto *c, uint8_t status)
1167 {
1168     VirtIODevice *vdev = VIRTIO_DEVICE(c);
1169     int queues = c->multiqueue ? c->max_queues : 1;
1170     CryptoDevBackend *b = c->cryptodev;
1171     CryptoDevBackendClient *cc = b->conf.peers.ccs[0];
1172 
1173     if (!cryptodev_get_vhost(cc, b, 0)) {
1174         return;
1175     }
1176 
1177     if ((virtio_crypto_started(c, status)) == !!c->vhost_started) {
1178         return;
1179     }
1180 
1181     if (!c->vhost_started) {
1182         int r;
1183 
1184         c->vhost_started = 1;
1185         r = cryptodev_vhost_start(vdev, queues);
1186         if (r < 0) {
1187             error_report("unable to start vhost crypto: %d: "
1188                          "falling back on userspace virtio", -r);
1189             c->vhost_started = 0;
1190         }
1191     } else {
1192         cryptodev_vhost_stop(vdev, queues);
1193         c->vhost_started = 0;
1194     }
1195 }
1196 
1197 static void virtio_crypto_set_status(VirtIODevice *vdev, uint8_t status)
1198 {
1199     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
1200 
1201     virtio_crypto_vhost_status(vcrypto, status);
1202 }
1203 
1204 static void virtio_crypto_guest_notifier_mask(VirtIODevice *vdev, int idx,
1205                                            bool mask)
1206 {
1207     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
1208     int queue = virtio_crypto_vq2q(idx);
1209 
1210     assert(vcrypto->vhost_started);
1211 
1212     /*
1213      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
1214      * as the Marco of configure interrupt's IDX, If this driver does not
1215      * support, the function will return
1216      */
1217 
1218     if (idx == VIRTIO_CONFIG_IRQ_IDX) {
1219         return;
1220     }
1221     cryptodev_vhost_virtqueue_mask(vdev, queue, idx, mask);
1222 }
1223 
1224 static bool virtio_crypto_guest_notifier_pending(VirtIODevice *vdev, int idx)
1225 {
1226     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
1227     int queue = virtio_crypto_vq2q(idx);
1228 
1229     assert(vcrypto->vhost_started);
1230 
1231     /*
1232      * Add the check for configure interrupt, Use VIRTIO_CONFIG_IRQ_IDX -1
1233      * as the Marco of configure interrupt's IDX, If this driver does not
1234      * support, the function will return
1235      */
1236 
1237     if (idx == VIRTIO_CONFIG_IRQ_IDX) {
1238         return false;
1239     }
1240     return cryptodev_vhost_virtqueue_pending(vdev, queue, idx);
1241 }
1242 
1243 static struct vhost_dev *virtio_crypto_get_vhost(VirtIODevice *vdev)
1244 {
1245     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
1246     CryptoDevBackend *b = vcrypto->cryptodev;
1247     CryptoDevBackendClient *cc = b->conf.peers.ccs[0];
1248     CryptoDevBackendVhost *vhost_crypto = cryptodev_get_vhost(cc, b, 0);
1249     return &vhost_crypto->dev;
1250 }
1251 
1252 static void virtio_crypto_class_init(ObjectClass *klass, void *data)
1253 {
1254     DeviceClass *dc = DEVICE_CLASS(klass);
1255     VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1256 
1257     device_class_set_props(dc, virtio_crypto_properties);
1258     dc->vmsd = &vmstate_virtio_crypto;
1259     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
1260     vdc->realize = virtio_crypto_device_realize;
1261     vdc->unrealize = virtio_crypto_device_unrealize;
1262     vdc->get_config = virtio_crypto_get_config;
1263     vdc->get_features = virtio_crypto_get_features;
1264     vdc->reset = virtio_crypto_reset;
1265     vdc->set_status = virtio_crypto_set_status;
1266     vdc->guest_notifier_mask = virtio_crypto_guest_notifier_mask;
1267     vdc->guest_notifier_pending = virtio_crypto_guest_notifier_pending;
1268     vdc->get_vhost = virtio_crypto_get_vhost;
1269 }
1270 
1271 static void virtio_crypto_instance_init(Object *obj)
1272 {
1273     VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(obj);
1274 
1275     /*
1276      * The default config_size is sizeof(struct virtio_crypto_config).
1277      * Can be overriden with virtio_crypto_set_config_size.
1278      */
1279     vcrypto->config_size = sizeof(struct virtio_crypto_config);
1280 }
1281 
1282 static const TypeInfo virtio_crypto_info = {
1283     .name = TYPE_VIRTIO_CRYPTO,
1284     .parent = TYPE_VIRTIO_DEVICE,
1285     .instance_size = sizeof(VirtIOCrypto),
1286     .instance_init = virtio_crypto_instance_init,
1287     .class_init = virtio_crypto_class_init,
1288 };
1289 
1290 static void virtio_register_types(void)
1291 {
1292     type_register_static(&virtio_crypto_info);
1293 }
1294 
1295 type_init(virtio_register_types)
1296