get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/132112/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 132112,
    "url": "http://patches.dpdk.org/api/patches/132112/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20230928095300.1353-4-gmuthukrishn@marvell.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<20230928095300.1353-4-gmuthukrishn@marvell.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20230928095300.1353-4-gmuthukrishn@marvell.com",
    "date": "2023-09-28T09:52:57",
    "name": "[RFC,3/6] vhost: add asymmetric RSA support",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "d2a525055cc1eeff7af45475541617a0a2ce0573",
    "submitter": {
        "id": 2301,
        "url": "http://patches.dpdk.org/api/people/2301/?format=api",
        "name": "Gowrishankar Muthukrishnan",
        "email": "gmuthukrishn@marvell.com"
    },
    "delegate": {
        "id": 6690,
        "url": "http://patches.dpdk.org/api/users/6690/?format=api",
        "username": "akhil",
        "first_name": "akhil",
        "last_name": "goyal",
        "email": "gakhil@marvell.com"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20230928095300.1353-4-gmuthukrishn@marvell.com/mbox/",
    "series": [
        {
            "id": 29674,
            "url": "http://patches.dpdk.org/api/series/29674/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=29674",
            "date": "2023-09-28T09:52:54",
            "name": "vhost: add asymmetric crypto support",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/29674/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/132112/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/132112/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from mails.dpdk.org (mails.dpdk.org [217.70.189.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id D9BF94265E;\n\tThu, 28 Sep 2023 11:53:41 +0200 (CEST)",
            "from mails.dpdk.org (localhost [127.0.0.1])\n\tby mails.dpdk.org (Postfix) with ESMTP id 802D140DF5;\n\tThu, 28 Sep 2023 11:53:32 +0200 (CEST)",
            "from mx0b-0016f401.pphosted.com (mx0a-0016f401.pphosted.com\n [67.231.148.174])\n by mails.dpdk.org (Postfix) with ESMTP id 9ABAE40DDA\n for <dev@dpdk.org>; Thu, 28 Sep 2023 11:53:30 +0200 (CEST)",
            "from pps.filterd (m0045849.ppops.net [127.0.0.1])\n by mx0a-0016f401.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id\n 38S8pJGZ018459; Thu, 28 Sep 2023 02:53:29 -0700",
            "from dc5-exch02.marvell.com ([199.233.59.182])\n by mx0a-0016f401.pphosted.com (PPS) with ESMTPS id 3tcu1qtdg9-1\n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NOT);\n Thu, 28 Sep 2023 02:53:29 -0700",
            "from DC5-EXCH02.marvell.com (10.69.176.39) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server (TLS) id 15.0.1497.48;\n Thu, 28 Sep 2023 02:53:27 -0700",
            "from maili.marvell.com (10.69.176.80) by DC5-EXCH02.marvell.com\n (10.69.176.39) with Microsoft SMTP Server id 15.0.1497.48 via Frontend\n Transport; Thu, 28 Sep 2023 02:53:27 -0700",
            "from BG-LT91401.marvell.com (BG-LT91401.marvell.com [10.28.168.34])\n by maili.marvell.com (Postfix) with ESMTP id 1F3C85C68F1;\n Thu, 28 Sep 2023 02:53:24 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=marvell.com;\n h=from : to : cc :\n subject : date : message-id : in-reply-to : references : mime-version :\n content-transfer-encoding : content-type; s=pfpt0220;\n bh=gKpveCPO7YSUoqZYc0ShKCcEwZEjKP1CoBO6LQwJtog=;\n b=DixwR71SEZs0CqX7d8sUNCaET+8TORm/axt5z16zEePYhHmNcXiH3CSsSD5eAOx7fEPl\n rdzGJBLN5PTbBufHUwQCQEtdxzcpj8kwTluQKABWNgswctCrHGK/Q7Q9ZTu17CC6Gunu\n eHnHwlItoFnPY0CkKlgrXF5Xj34faoF0vSRT06JBihiVSBNftqZVoDXweq4pCXEv/Xdu\n +OHUYT63SJO69RPiTNmzDEOau74tIzELhqESJTJo8TGTi8l63/rHic7dCYFW7jes6iIx\n 99xNZVYLwckhZZV11XdNcMqeVQdmCzBPx6zDFqoq6bISlDuHbkCxQgcjVKYm/aOj5AKV Gw==",
        "From": "Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>",
        "To": "<dev@dpdk.org>",
        "CC": "<anoobj@marvell.com>, Akhil Goyal <gakhil@marvell.com>, Fan Zhang\n <fanzhang.oss@gmail.com>, Kai Ji <kai.ji@intel.com>, Arkadiusz Kusztal\n <arkadiuszx.kusztal@intel.com>,\n Maxime Coquelin <maxime.coquelin@redhat.com>,\n Chenbo Xia <chenbo.xia@intel.com>, Jay Zhou <jianjay.zhou@huawei.com>,\n Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>",
        "Subject": "[RFC 3/6] vhost: add asymmetric RSA support",
        "Date": "Thu, 28 Sep 2023 15:22:57 +0530",
        "Message-ID": "<20230928095300.1353-4-gmuthukrishn@marvell.com>",
        "X-Mailer": "git-send-email 2.21.0",
        "In-Reply-To": "<20230928095300.1353-1-gmuthukrishn@marvell.com>",
        "References": "<20230928095300.1353-1-gmuthukrishn@marvell.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Content-Type": "text/plain",
        "X-Proofpoint-GUID": "ygbor7tJ5EU9b1C4_jb5OS1ORjsr0CnD",
        "X-Proofpoint-ORIG-GUID": "ygbor7tJ5EU9b1C4_jb5OS1ORjsr0CnD",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.267,Aquarius:18.0.980,Hydra:6.0.619,FMLib:17.11.176.26\n definitions=2023-09-28_07,2023-09-27_01,2023-05-22_02",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.29",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n <mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org"
    },
    "content": "Support asymmetric RSA crypto operations in vhost-user.\n\nSigned-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>\n---\n lib/cryptodev/cryptodev_pmd.h |   6 +\n lib/vhost/rte_vhost_crypto.h  |  14 +-\n lib/vhost/vhost.c             |  11 +-\n lib/vhost/vhost.h             |   1 +\n lib/vhost/vhost_crypto.c      | 551 +++++++++++++++++++++++++++++++---\n lib/vhost/vhost_user.c        |   4 +\n lib/vhost/vhost_user.h        |  34 ++-\n lib/vhost/virtio_crypto.h     |  87 +++++-\n 8 files changed, 655 insertions(+), 53 deletions(-)",
    "diff": "diff --git a/lib/cryptodev/cryptodev_pmd.h b/lib/cryptodev/cryptodev_pmd.h\nindex 3bb3d95c13..bbda72a238 100644\n--- a/lib/cryptodev/cryptodev_pmd.h\n+++ b/lib/cryptodev/cryptodev_pmd.h\n@@ -696,6 +696,12 @@ struct rte_cryptodev_asym_session {\n \tuint8_t sess_private_data[];\n };\n \n+/**\n+ * Helper macro to get session private data\n+ */\n+#define CRYPTODEV_GET_ASYM_SESS_PRIV(s) \\\n+\t((void *)(((struct rte_cryptodev_asym_session *)s)->sess_private_data))\n+\n #ifdef __cplusplus\n }\n #endif\ndiff --git a/lib/vhost/rte_vhost_crypto.h b/lib/vhost/rte_vhost_crypto.h\nindex 2b01ecda08..e03542de26 100644\n--- a/lib/vhost/rte_vhost_crypto.h\n+++ b/lib/vhost/rte_vhost_crypto.h\n@@ -52,8 +52,10 @@ rte_vhost_crypto_driver_start(const char *path);\n  * @param cryptodev_id\n  *  The identifier of DPDK Cryptodev, the same cryptodev_id can be assigned to\n  *  multiple Vhost-crypto devices.\n- * @param sess_pool\n- *  The pointer to the created cryptodev session pool.\n+ * @param sym_sess_pool\n+ *  The pointer to the created cryptodev sym session pool.\n+ * @param asym_sess_pool\n+ *  The pointer to the created cryptodev asym session pool.\n  * @param socket_id\n  *  NUMA Socket ID to allocate resources on. *\n  * @return\n@@ -62,7 +64,7 @@ rte_vhost_crypto_driver_start(const char *path);\n  */\n int\n rte_vhost_crypto_create(int vid, uint8_t cryptodev_id,\n-\t\tstruct rte_mempool *sess_pool,\n+\t\tstruct rte_mempool *sym_sess_pool, struct rte_mempool *asym_sess_pool,\n \t\tint socket_id);\n \n /**\n@@ -116,6 +118,10 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,\n  * dequeued from the cryptodev, this function shall be called to write the\n  * processed data back to the vring descriptor (if no-copy is turned off).\n  *\n+ * @param vid\n+ *  The identifier of the vhost device.\n+ * @param qid\n+ *  Virtio queue index.\n  * @param ops\n  *  The address of an array of *rte_crypto_op* structure that was dequeued\n  *  from cryptodev.\n@@ -130,7 +136,7 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,\n  *  The number of ops processed.\n  */\n uint16_t\n-rte_vhost_crypto_finalize_requests(struct rte_crypto_op **ops,\n+rte_vhost_crypto_finalize_requests(int vid, int qid, struct rte_crypto_op **ops,\n \t\tuint16_t nb_ops, int *callfds, uint16_t *nb_callfds);\n \n #ifdef __cplusplus\ndiff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c\nindex c03bb9c6eb..675459e05b 100644\n--- a/lib/vhost/vhost.c\n+++ b/lib/vhost/vhost.c\n@@ -631,8 +631,12 @@ alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)\n \n \t/* Also allocate holes, if any, up to requested vring index. */\n \tfor (i = 0; i <= vring_idx; i++) {\n-\t\tif (dev->virtqueue[i])\n+\t\trte_spinlock_lock(&dev->virtqueue_lock);\n+\t\tif (dev->virtqueue[i]) {\n+\t\t\trte_spinlock_unlock(&dev->virtqueue_lock);\n \t\t\tcontinue;\n+\t\t}\n+\t\trte_spinlock_unlock(&dev->virtqueue_lock);\n \n \t\tvq = rte_zmalloc(NULL, sizeof(struct vhost_virtqueue), 0);\n \t\tif (vq == NULL) {\n@@ -642,13 +646,15 @@ alloc_vring_queue(struct virtio_net *dev, uint32_t vring_idx)\n \t\t\treturn -1;\n \t\t}\n \n-\t\tdev->virtqueue[i] = vq;\n \t\tinit_vring_queue(dev, vq, i);\n \t\trte_rwlock_init(&vq->access_lock);\n \t\trte_rwlock_init(&vq->iotlb_lock);\n \t\tvq->avail_wrap_counter = 1;\n \t\tvq->used_wrap_counter = 1;\n \t\tvq->signalled_used_valid = false;\n+\t\trte_spinlock_lock(&dev->virtqueue_lock);\n+\t\tdev->virtqueue[i] = vq;\n+\t\trte_spinlock_unlock(&dev->virtqueue_lock);\n \t}\n \n \tdev->nr_vring = RTE_MAX(dev->nr_vring, vring_idx + 1);\n@@ -735,6 +741,7 @@ vhost_new_device(struct vhost_backend_ops *ops)\n \tdev->postcopy_ufd = -1;\n \trte_spinlock_init(&dev->backend_req_lock);\n \tdev->backend_ops = ops;\n+\trte_spinlock_init(&dev->virtqueue_lock);\n \n \treturn i;\n }\ndiff --git a/lib/vhost/vhost.h b/lib/vhost/vhost.h\nindex 9723429b1c..9ba8cca5d4 100644\n--- a/lib/vhost/vhost.h\n+++ b/lib/vhost/vhost.h\n@@ -489,6 +489,7 @@ struct virtio_net {\n \n \tint\t\t\textbuf;\n \tint\t\t\tlinearbuf;\n+\trte_spinlock_t virtqueue_lock;\n \tstruct vhost_virtqueue\t*virtqueue[VHOST_MAX_QUEUE_PAIRS * 2];\n \n \trte_rwlock_t\tiotlb_pending_lock;\ndiff --git a/lib/vhost/vhost_crypto.c b/lib/vhost/vhost_crypto.c\nindex 9bf5ef67b9..66fa53baea 100644\n--- a/lib/vhost/vhost_crypto.c\n+++ b/lib/vhost/vhost_crypto.c\n@@ -53,6 +53,15 @@\n  */\n #define vhost_crypto_desc vring_desc\n \n+struct vhost_crypto_session {\n+\tRTE_STD_C11\n+\tunion {\n+\t\tstruct rte_cryptodev_asym_session *asym;\n+\t\tstruct rte_cryptodev_sym_session *sym;\n+\t};\n+\tenum rte_crypto_op_type type;\n+};\n+\n static int\n cipher_algo_transform(uint32_t virtio_cipher_algo,\n \t\tenum rte_crypto_cipher_algorithm *algo)\n@@ -196,7 +205,8 @@ struct vhost_crypto {\n \t */\n \tstruct rte_hash *session_map;\n \tstruct rte_mempool *mbuf_pool;\n-\tstruct rte_mempool *sess_pool;\n+\tstruct rte_mempool *sym_sess_pool;\n+\tstruct rte_mempool *asym_sess_pool;\n \tstruct rte_mempool *wb_pool;\n \n \t/** DPDK cryptodev ID */\n@@ -205,8 +215,10 @@ struct vhost_crypto {\n \n \tuint64_t last_session_id;\n \n-\tuint64_t cache_session_id;\n-\tstruct rte_cryptodev_sym_session *cache_session;\n+\tuint64_t cache_sym_session_id;\n+\tvoid *cache_sym_session;\n+\tuint64_t cache_asym_session_id;\n+\tvoid *cache_asym_session;\n \t/** socket id for the device */\n \tint socket_id;\n \n@@ -236,7 +248,7 @@ struct vhost_crypto_data_req {\n \n static int\n transform_cipher_param(struct rte_crypto_sym_xform *xform,\n-\t\tVhostUserCryptoSessionParam *param)\n+\t\tVhostUserCryptoSymSessionParam *param)\n {\n \tint ret;\n \n@@ -272,7 +284,7 @@ transform_cipher_param(struct rte_crypto_sym_xform *xform,\n \n static int\n transform_chain_param(struct rte_crypto_sym_xform *xforms,\n-\t\tVhostUserCryptoSessionParam *param)\n+\t\tVhostUserCryptoSymSessionParam *param)\n {\n \tstruct rte_crypto_sym_xform *xform_cipher, *xform_auth;\n \tint ret;\n@@ -333,17 +345,17 @@ transform_chain_param(struct rte_crypto_sym_xform *xforms,\n }\n \n static void\n-vhost_crypto_create_sess(struct vhost_crypto *vcrypto,\n+vhost_crypto_create_sym_sess(struct vhost_crypto *vcrypto,\n \t\tVhostUserCryptoSessionParam *sess_param)\n {\n \tstruct rte_crypto_sym_xform xform1 = {0}, xform2 = {0};\n \tstruct rte_cryptodev_sym_session *session;\n \tint ret;\n \n-\tswitch (sess_param->op_type) {\n+\tswitch (sess_param->u.sym_sess.op_type) {\n \tcase VIRTIO_CRYPTO_SYM_OP_NONE:\n \tcase VIRTIO_CRYPTO_SYM_OP_CIPHER:\n-\t\tret = transform_cipher_param(&xform1, sess_param);\n+\t\tret = transform_cipher_param(&xform1, &sess_param->u.sym_sess);\n \t\tif (unlikely(ret)) {\n \t\t\tVC_LOG_ERR(\"Error transform session msg (%i)\", ret);\n \t\t\tsess_param->session_id = ret;\n@@ -351,7 +363,7 @@ vhost_crypto_create_sess(struct vhost_crypto *vcrypto,\n \t\t}\n \t\tbreak;\n \tcase VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:\n-\t\tif (unlikely(sess_param->hash_mode !=\n+\t\tif (unlikely(sess_param->u.sym_sess.hash_mode !=\n \t\t\t\tVIRTIO_CRYPTO_SYM_HASH_MODE_AUTH)) {\n \t\t\tsess_param->session_id = -VIRTIO_CRYPTO_NOTSUPP;\n \t\t\tVC_LOG_ERR(\"Error transform session message (%i)\",\n@@ -361,7 +373,7 @@ vhost_crypto_create_sess(struct vhost_crypto *vcrypto,\n \n \t\txform1.next = &xform2;\n \n-\t\tret = transform_chain_param(&xform1, sess_param);\n+\t\tret = transform_chain_param(&xform1, &sess_param->u.sym_sess);\n \t\tif (unlikely(ret)) {\n \t\t\tVC_LOG_ERR(\"Error transform session message (%i)\", ret);\n \t\t\tsess_param->session_id = ret;\n@@ -376,7 +388,7 @@ vhost_crypto_create_sess(struct vhost_crypto *vcrypto,\n \t}\n \n \tsession = rte_cryptodev_sym_session_create(vcrypto->cid, &xform1,\n-\t\t\tvcrypto->sess_pool);\n+\t\t\tvcrypto->sym_sess_pool);\n \tif (!session) {\n \t\tVC_LOG_ERR(\"Failed to create session\");\n \t\tsess_param->session_id = -VIRTIO_CRYPTO_ERR;\n@@ -401,22 +413,282 @@ vhost_crypto_create_sess(struct vhost_crypto *vcrypto,\n \tvcrypto->last_session_id++;\n }\n \n+static int\n+tlv_decode(uint8_t *tlv, uint8_t type, uint8_t **data, size_t *data_len)\n+{\n+\tsize_t tlen = -EINVAL, len;\n+\n+\tif (tlv[0] != type)\n+\t\treturn -EINVAL;\n+\n+\tif (tlv[1] == 0x82) {\n+\t\tlen = (tlv[2] << 8) | tlv[3];\n+\t\t*data = rte_malloc(NULL, len, 0);\n+\t\trte_memcpy(*data, &tlv[4], len);\n+\t\ttlen = len + 4;\n+\t} else if (tlv[1] == 0x81) {\n+\t\tlen = tlv[2];\n+\t\t*data = rte_malloc(NULL, len, 0);\n+\t\trte_memcpy(*data, &tlv[3], len);\n+\t\ttlen = len + 3;\n+\t} else {\n+\t\tlen = tlv[1];\n+\t\t*data = rte_malloc(NULL, len, 0);\n+\t\trte_memcpy(*data, &tlv[2], len);\n+\t\ttlen = len + 2;\n+\t}\n+\n+\t*data_len = len;\n+\treturn tlen;\n+}\n+\n+static int\n+virtio_crypto_asym_rsa_der_to_xform(uint8_t *der, size_t der_len,\n+\t\tstruct rte_crypto_asym_xform *xform)\n+{\n+\tuint8_t *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, *dp = NULL,\n+\t\t*dq = NULL, *qinv = NULL, *v = NULL, *tlv;\n+\tsize_t nlen, elen, dlen, plen, qlen, dplen, dqlen, qinvlen, vlen;\n+\tint len, i;\n+\n+\tRTE_SET_USED(der_len);\n+\n+\tfor (i = 0; i < 8; i++) {\n+\t\tif (der[i] == 0x30) {\n+\t\t\tder = &der[i];\n+\t\t\tbreak;\n+\t\t}\n+\t}\n+\n+\tif (der[0] != 0x30)\n+\t\treturn -EINVAL;\n+\n+\tif (der[1] == 0x82)\n+\t\ttlv = &der[4];\n+\telse if (der[1] == 0x81)\n+\t\ttlv = &der[3];\n+\telse\n+\t\treturn -EINVAL;\n+\n+\tlen = tlv_decode(tlv, 0x02, &v, &vlen);\n+\tif (len < 0 || v[0] != 0x0 || vlen != 1) {\n+\t\tlen = -EINVAL;\n+\t\tgoto _error;\n+\t}\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &n, &nlen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &e, &elen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &d, &dlen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &p, &plen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &q, &qlen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &dp, &dplen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &dq, &dqlen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\ttlv = tlv + len;\n+\tlen = tlv_decode(tlv, 0x02, &qinv, &qinvlen);\n+\tif (len < 0)\n+\t\tgoto _error;\n+\n+\txform->rsa.n.data = n;\n+\txform->rsa.n.length = nlen;\n+\txform->rsa.e.data = e;\n+\txform->rsa.e.length = elen;\n+\txform->rsa.d.data = d;\n+\txform->rsa.d.length = dlen;\n+\txform->rsa.qt.p.data = p;\n+\txform->rsa.qt.p.length = plen;\n+\txform->rsa.qt.q.data = q;\n+\txform->rsa.qt.q.length = qlen;\n+\txform->rsa.qt.dP.data = dp;\n+\txform->rsa.qt.dP.length = dplen;\n+\txform->rsa.qt.dQ.data = dq;\n+\txform->rsa.qt.dQ.length = dqlen;\n+\txform->rsa.qt.qInv.data = qinv;\n+\txform->rsa.qt.qInv.length = qinvlen;\n+\n+\tRTE_ASSERT((tlv + len - &der[0]) == der_len);\n+\treturn 0;\n+_error:\n+\trte_free(v);\n+\trte_free(n);\n+\trte_free(e);\n+\trte_free(d);\n+\trte_free(p);\n+\trte_free(q);\n+\trte_free(dp);\n+\trte_free(dq);\n+\trte_free(qinv);\n+\treturn len;\n+}\n+\n+static int\n+transform_rsa_param(struct rte_crypto_asym_xform *xform,\n+\t\tVhostUserCryptoAsymSessionParam *param)\n+{\n+\tint ret = -EINVAL;\n+\n+\tret = virtio_crypto_asym_rsa_der_to_xform(param->key_buf, param->key_len, xform);\n+\tif (ret < 0)\n+\t\tgoto _error;\n+\n+\tswitch (param->u.rsa.padding_algo) {\n+\tcase VIRTIO_CRYPTO_RSA_RAW_PADDING:\n+\t\txform->rsa.padding.type = RTE_CRYPTO_RSA_PADDING_NONE;\n+\t\tbreak;\n+\tcase VIRTIO_CRYPTO_RSA_PKCS1_PADDING:\n+\t\txform->rsa.padding.type = RTE_CRYPTO_RSA_PADDING_PKCS1_5;\n+\t\tbreak;\n+\tdefault:\n+\t\tVC_LOG_ERR(\"Unknown padding type\");\n+\t\tgoto _error;\n+\t}\n+\n+\tswitch (param->u.rsa.private_key_type) {\n+\tcase VIRTIO_CRYPTO_RSA_PRIVATE_KEY_EXP:\n+\t\txform->rsa.key_type = RTE_RSA_KEY_TYPE_EXP;\n+\t\tbreak;\n+\tcase VIRTIO_CRYPTO_RSA_PRIVATE_KEY_QT:\n+\t\txform->rsa.key_type = RTE_RSA_KEY_TYPE_QT;\n+\t\tbreak;\n+\tdefault:\n+\t\tVC_LOG_ERR(\"Unknown private key type\");\n+\t\tgoto _error;\n+\t}\n+\n+\txform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;\n+_error:\n+\treturn ret;\n+}\n+\n+static void\n+vhost_crypto_create_asym_sess(struct vhost_crypto *vcrypto,\n+\t\tVhostUserCryptoSessionParam *sess_param)\n+{\n+\tstruct rte_cryptodev_asym_session *session = NULL;\n+\tstruct vhost_crypto_session *vhost_session;\n+\tstruct rte_crypto_asym_xform xform = {0};\n+\tint ret;\n+\n+\tswitch (sess_param->u.asym_sess.algo) {\n+\tcase VIRTIO_CRYPTO_AKCIPHER_RSA:\n+\t\tret = transform_rsa_param(&xform, &sess_param->u.asym_sess);\n+\t\tif (unlikely(ret)) {\n+\t\t\tVC_LOG_ERR(\"Error transform session msg (%i)\", ret);\n+\t\t\tsess_param->session_id = ret;\n+\t\t\treturn;\n+\t\t}\n+\t\tbreak;\n+\tdefault:\n+\t\tVC_LOG_ERR(\"Invalid op algo\");\n+\t\tsess_param->session_id = -VIRTIO_CRYPTO_ERR;\n+\t\treturn;\n+\t}\n+\n+\tret = rte_cryptodev_asym_session_create(vcrypto->cid, &xform,\n+\t\t\tvcrypto->asym_sess_pool, (void *)&session);\n+\tif (!session) {\n+\t\tVC_LOG_ERR(\"Failed to create session\");\n+\t\tsess_param->session_id = -VIRTIO_CRYPTO_ERR;\n+\t\treturn;\n+\t}\n+\n+\t/* insert session to map */\n+\tvhost_session = rte_malloc(NULL, sizeof(*vhost_session), 0);\n+\tif (vhost_session == NULL) {\n+\t\tVC_LOG_ERR(\"Failed to alloc session memory\");\n+\t\tsess_param->session_id = -VIRTIO_CRYPTO_ERR;\n+\t\treturn;\n+\t}\n+\n+\tvhost_session->type = RTE_CRYPTO_OP_TYPE_ASYMMETRIC;\n+\tvhost_session->asym = session;\n+\tif ((rte_hash_add_key_data(vcrypto->session_map,\n+\t\t\t&vcrypto->last_session_id, vhost_session) < 0)) {\n+\t\tVC_LOG_ERR(\"Failed to insert session to hash table\");\n+\n+\t\tif (rte_cryptodev_asym_session_free(vcrypto->cid, session) < 0)\n+\t\t\tVC_LOG_ERR(\"Failed to free session\");\n+\t\tsess_param->session_id = -VIRTIO_CRYPTO_ERR;\n+\t\treturn;\n+\t}\n+\n+\tVC_LOG_INFO(\"Session %\"PRIu64\" created for vdev %i.\",\n+\t\t\tvcrypto->last_session_id, vcrypto->dev->vid);\n+\n+\tsess_param->session_id = vcrypto->last_session_id;\n+\tvcrypto->last_session_id++;\n+}\n+\n+static void\n+vhost_crypto_create_sess(struct vhost_crypto *vcrypto,\n+\t\tVhostUserCryptoSessionParam *sess_param)\n+{\n+\tif (sess_param->op_code == VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION)\n+\t\tvhost_crypto_create_asym_sess(vcrypto, sess_param);\n+\telse\n+\t\tvhost_crypto_create_sym_sess(vcrypto, sess_param);\n+}\n+\n static int\n vhost_crypto_close_sess(struct vhost_crypto *vcrypto, uint64_t session_id)\n {\n-\tstruct rte_cryptodev_sym_session *session;\n+\tstruct rte_cryptodev_asym_session *asym_session = NULL;\n+\tstruct rte_cryptodev_sym_session *sym_session = NULL;\n+\tstruct vhost_crypto_session *vhost_session = NULL;\n \tuint64_t sess_id = session_id;\n \tint ret;\n \n \tret = rte_hash_lookup_data(vcrypto->session_map, &sess_id,\n-\t\t\t(void **)&session);\n-\n+\t\t\t\t(void **)&vhost_session);\n \tif (unlikely(ret < 0)) {\n-\t\tVC_LOG_ERR(\"Failed to delete session %\"PRIu64\".\", session_id);\n+\t\tVC_LOG_ERR(\"Failed to find session for id %\"PRIu64\".\", session_id);\n \t\treturn -VIRTIO_CRYPTO_INVSESS;\n \t}\n \n-\tif (rte_cryptodev_sym_session_free(vcrypto->cid, session) < 0) {\n+\tif (vhost_session->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {\n+\t\tsym_session = vhost_session->sym;\n+\t} else if (vhost_session->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {\n+\t\tasym_session = vhost_session->asym;\n+\t} else {\n+\t\tVC_LOG_ERR(\"Invalid session for id %\"PRIu64\".\", session_id);\n+\t\treturn -VIRTIO_CRYPTO_INVSESS;\n+\t}\n+\n+\tif (sym_session != NULL &&\n+\t\t    rte_cryptodev_sym_session_free(vcrypto->cid, sym_session) < 0) {\n+\t\tVC_LOG_DBG(\"Failed to free session\");\n+\t\treturn -VIRTIO_CRYPTO_ERR;\n+\t}\n+\n+\tif (asym_session != NULL &&\n+\t\trte_cryptodev_asym_session_free(vcrypto->cid, asym_session) < 0) {\n \t\tVC_LOG_DBG(\"Failed to free session\");\n \t\treturn -VIRTIO_CRYPTO_ERR;\n \t}\n@@ -429,6 +701,7 @@ vhost_crypto_close_sess(struct vhost_crypto *vcrypto, uint64_t session_id)\n \tVC_LOG_INFO(\"Session %\"PRIu64\" deleted for vdev %i.\", sess_id,\n \t\t\tvcrypto->dev->vid);\n \n+\trte_free(vhost_session);\n \treturn 0;\n }\n \n@@ -1122,6 +1395,118 @@ prepare_sym_chain_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,\n \treturn ret;\n }\n \n+static __rte_always_inline uint8_t\n+vhost_crypto_check_akcipher_request(struct virtio_crypto_akcipher_data_req *req)\n+{\n+\tRTE_SET_USED(req);\n+\treturn VIRTIO_CRYPTO_OK;\n+}\n+\n+static __rte_always_inline uint8_t\n+prepare_asym_rsa_op(struct vhost_crypto *vcrypto, struct rte_crypto_op *op,\n+\t\tstruct vhost_crypto_data_req *vc_req,\n+\t\tstruct virtio_crypto_op_data_req *req,\n+\t\tstruct vhost_crypto_desc *head,\n+\t\tuint32_t max_n_descs)\n+{\n+\tuint8_t ret = vhost_crypto_check_akcipher_request(&req->u.akcipher_req);\n+\tstruct rte_crypto_rsa_op_param *rsa = &op->asym->rsa;\n+\tstruct vhost_crypto_desc *desc = head;\n+\tuint16_t wlen = 0;\n+\n+\tif (unlikely(ret != VIRTIO_CRYPTO_OK))\n+\t\tgoto error_exit;\n+\n+\t/* prepare */\n+\tswitch (vcrypto->option) {\n+\tcase RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE:\n+\t\tvc_req->wb_pool = vcrypto->wb_pool;\n+\t\tif (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_SIGN) {\n+\t\t\trsa->op_type = RTE_CRYPTO_ASYM_OP_SIGN;\n+\t\t\trsa->message.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);\n+\t\t\trsa->message.length = req->u.akcipher_req.para.src_data_len;\n+\t\t\trsa->sign.length = req->u.akcipher_req.para.dst_data_len;\n+\t\t\twlen = rsa->sign.length;\n+\t\t\tdesc = find_write_desc(head, desc, max_n_descs);\n+\t\t\tif (unlikely(!desc)) {\n+\t\t\t\tVC_LOG_ERR(\"Cannot find write location\");\n+\t\t\t\tret = VIRTIO_CRYPTO_BADMSG;\n+\t\t\t\tgoto error_exit;\n+\t\t\t}\n+\n+\t\t\trsa->sign.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RW);\n+\t\t\tif (unlikely(rsa->sign.data == NULL)) {\n+\t\t\t\tret = VIRTIO_CRYPTO_ERR;\n+\t\t\t\tgoto error_exit;\n+\t\t\t}\n+\n+\t\t\tdesc += 1;\n+\t\t} else if (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_VERIFY) {\n+\t\t\trsa->op_type = RTE_CRYPTO_ASYM_OP_VERIFY;\n+\t\t\trsa->sign.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);\n+\t\t\trsa->sign.length = req->u.akcipher_req.para.src_data_len;\n+\t\t\tdesc += 1;\n+\t\t\trsa->message.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);\n+\t\t\trsa->message.length = req->u.akcipher_req.para.dst_data_len;\n+\t\t\tdesc += 1;\n+\t\t} else if (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_ENCRYPT) {\n+\t\t\trsa->op_type = RTE_CRYPTO_ASYM_OP_ENCRYPT;\n+\t\t\trsa->message.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);\n+\t\t\trsa->message.length = req->u.akcipher_req.para.src_data_len;\n+\t\t\trsa->cipher.length = req->u.akcipher_req.para.dst_data_len;\n+\t\t\twlen = rsa->cipher.length;\n+\t\t\tdesc = find_write_desc(head, desc, max_n_descs);\n+\t\t\tif (unlikely(!desc)) {\n+\t\t\t\tVC_LOG_ERR(\"Cannot find write location\");\n+\t\t\t\tret = VIRTIO_CRYPTO_BADMSG;\n+\t\t\t\tgoto error_exit;\n+\t\t\t}\n+\n+\t\t\trsa->cipher.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RW);\n+\t\t\tif (unlikely(rsa->cipher.data == NULL)) {\n+\t\t\t\tret = VIRTIO_CRYPTO_ERR;\n+\t\t\t\tgoto error_exit;\n+\t\t\t}\n+\n+\t\t\tdesc += 1;\n+\t\t} else if (req->header.opcode == VIRTIO_CRYPTO_AKCIPHER_DECRYPT) {\n+\t\t\trsa->op_type = RTE_CRYPTO_ASYM_OP_DECRYPT;\n+\t\t\trsa->cipher.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);\n+\t\t\trsa->cipher.length = req->u.akcipher_req.para.src_data_len;\n+\t\t\tdesc += 1;\n+\t\t\trsa->message.data = get_data_ptr(vc_req, desc, VHOST_ACCESS_RO);\n+\t\t\trsa->message.length = req->u.akcipher_req.para.dst_data_len;\n+\t\t\tdesc += 1;\n+\t\t} else {\n+\t\t\tgoto error_exit;\n+\t\t}\n+\t\tbreak;\n+\tcase RTE_VHOST_CRYPTO_ZERO_COPY_ENABLE:\n+\tdefault:\n+\t\tret = VIRTIO_CRYPTO_BADMSG;\n+\t\tgoto error_exit;\n+\t}\n+\n+\top->type = RTE_CRYPTO_OP_TYPE_ASYMMETRIC;\n+\top->sess_type = RTE_CRYPTO_OP_WITH_SESSION;\n+\n+\tvc_req->inhdr = get_data_ptr(vc_req, desc, VHOST_ACCESS_WO);\n+\tif (unlikely(vc_req->inhdr == NULL)) {\n+\t\tret = VIRTIO_CRYPTO_BADMSG;\n+\t\tgoto error_exit;\n+\t}\n+\n+\tvc_req->inhdr->status = VIRTIO_CRYPTO_OK;\n+\tvc_req->len = wlen + INHDR_LEN;\n+\treturn 0;\n+error_exit:\n+\tif (vc_req->wb)\n+\t\tfree_wb_data(vc_req->wb, vc_req->wb_pool);\n+\n+\tvc_req->len = INHDR_LEN;\n+\treturn ret;\n+}\n+\n /**\n  * Process on descriptor\n  */\n@@ -1132,17 +1517,21 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,\n \t\tuint16_t desc_idx)\n \t__rte_no_thread_safety_analysis /* FIXME: requires iotlb_lock? */\n {\n-\tstruct vhost_crypto_data_req *vc_req = rte_mbuf_to_priv(op->sym->m_src);\n-\tstruct rte_cryptodev_sym_session *session;\n+\tstruct vhost_crypto_data_req *vc_req, *vc_req_out;\n+\tstruct rte_cryptodev_asym_session *asym_session;\n+\tstruct rte_cryptodev_sym_session *sym_session;\n+\tstruct vhost_crypto_session *vhost_session;\n+\tstruct vhost_crypto_desc *desc = descs;\n+\tuint32_t nb_descs = 0, max_n_descs, i;\n+\tstruct vhost_crypto_data_req data_req;\n \tstruct virtio_crypto_op_data_req req;\n \tstruct virtio_crypto_inhdr *inhdr;\n-\tstruct vhost_crypto_desc *desc = descs;\n \tstruct vring_desc *src_desc;\n \tuint64_t session_id;\n \tuint64_t dlen;\n-\tuint32_t nb_descs = 0, max_n_descs, i;\n \tint err;\n \n+\tvc_req = &data_req;\n \tvc_req->desc_idx = desc_idx;\n \tvc_req->dev = vcrypto->dev;\n \tvc_req->vq = vq;\n@@ -1225,12 +1614,14 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,\n \tswitch (req.header.opcode) {\n \tcase VIRTIO_CRYPTO_CIPHER_ENCRYPT:\n \tcase VIRTIO_CRYPTO_CIPHER_DECRYPT:\n+\t\tvc_req_out = rte_mbuf_to_priv(op->sym->m_src);\n+\t\trte_memcpy(vc_req_out, vc_req, sizeof(struct vhost_crypto_data_req));\n \t\tsession_id = req.header.session_id;\n \n \t\t/* one branch to avoid unnecessary table lookup */\n-\t\tif (vcrypto->cache_session_id != session_id) {\n+\t\tif (vcrypto->cache_sym_session_id != session_id) {\n \t\t\terr = rte_hash_lookup_data(vcrypto->session_map,\n-\t\t\t\t\t&session_id, (void **)&session);\n+\t\t\t\t\t&session_id, (void **)&vhost_session);\n \t\t\tif (unlikely(err < 0)) {\n \t\t\t\terr = VIRTIO_CRYPTO_ERR;\n \t\t\t\tVC_LOG_ERR(\"Failed to find session %\"PRIu64,\n@@ -1238,13 +1629,14 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,\n \t\t\t\tgoto error_exit;\n \t\t\t}\n \n-\t\t\tvcrypto->cache_session = session;\n-\t\t\tvcrypto->cache_session_id = session_id;\n+\t\t\tvcrypto->cache_sym_session = vhost_session->sym;\n+\t\t\tvcrypto->cache_sym_session_id = session_id;\n \t\t}\n \n-\t\tsession = vcrypto->cache_session;\n+\t\tsym_session = vcrypto->cache_sym_session;\n+\t\top->type = RTE_CRYPTO_OP_TYPE_SYMMETRIC;\n \n-\t\terr = rte_crypto_op_attach_sym_session(op, session);\n+\t\terr = rte_crypto_op_attach_sym_session(op, sym_session);\n \t\tif (unlikely(err < 0)) {\n \t\t\terr = VIRTIO_CRYPTO_ERR;\n \t\t\tVC_LOG_ERR(\"Failed to attach session to op\");\n@@ -1256,12 +1648,12 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,\n \t\t\terr = VIRTIO_CRYPTO_NOTSUPP;\n \t\t\tbreak;\n \t\tcase VIRTIO_CRYPTO_SYM_OP_CIPHER:\n-\t\t\terr = prepare_sym_cipher_op(vcrypto, op, vc_req,\n+\t\t\terr = prepare_sym_cipher_op(vcrypto, op, vc_req_out,\n \t\t\t\t\t&req.u.sym_req.u.cipher, desc,\n \t\t\t\t\tmax_n_descs);\n \t\t\tbreak;\n \t\tcase VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING:\n-\t\t\terr = prepare_sym_chain_op(vcrypto, op, vc_req,\n+\t\t\terr = prepare_sym_chain_op(vcrypto, op, vc_req_out,\n \t\t\t\t\t&req.u.sym_req.u.chain, desc,\n \t\t\t\t\tmax_n_descs);\n \t\t\tbreak;\n@@ -1270,6 +1662,53 @@ vhost_crypto_process_one_req(struct vhost_crypto *vcrypto,\n \t\t\tVC_LOG_ERR(\"Failed to process sym request\");\n \t\t\tgoto error_exit;\n \t\t}\n+\t\tbreak;\n+\tcase VIRTIO_CRYPTO_AKCIPHER_SIGN:\n+\tcase VIRTIO_CRYPTO_AKCIPHER_VERIFY:\n+\tcase VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:\n+\tcase VIRTIO_CRYPTO_AKCIPHER_DECRYPT:\n+\t\tsession_id = req.header.session_id;\n+\n+\t\t/* one branch to avoid unnecessary table lookup */\n+\t\tif (vcrypto->cache_asym_session_id != session_id) {\n+\t\t\terr = rte_hash_lookup_data(vcrypto->session_map,\n+\t\t\t\t\t&session_id, (void **)&vhost_session);\n+\t\t\tif (unlikely(err < 0)) {\n+\t\t\t\terr = VIRTIO_CRYPTO_ERR;\n+\t\t\t\tVC_LOG_ERR(\"Failed to find asym session %\"PRIu64,\n+\t\t\t\t\t\t   session_id);\n+\t\t\t\tgoto error_exit;\n+\t\t\t}\n+\n+\t\t\tvcrypto->cache_asym_session = vhost_session->asym;\n+\t\t\tvcrypto->cache_asym_session_id = session_id;\n+\t\t}\n+\n+\t\tasym_session = vcrypto->cache_asym_session;\n+\t\top->type = RTE_CRYPTO_OP_TYPE_ASYMMETRIC;\n+\n+\t\terr = rte_crypto_op_attach_asym_session(op, asym_session);\n+\t\tif (unlikely(err < 0)) {\n+\t\t\terr = VIRTIO_CRYPTO_ERR;\n+\t\t\tVC_LOG_ERR(\"Failed to attach asym session to op\");\n+\t\t\tgoto error_exit;\n+\t\t}\n+\n+\t\tvc_req_out = rte_cryptodev_asym_session_get_user_data(asym_session);\n+\t\trte_memcpy(vc_req_out, vc_req, sizeof(struct vhost_crypto_data_req));\n+\t\tvc_req_out->wb = NULL;\n+\n+\t\tswitch (req.header.algo) {\n+\t\tcase VIRTIO_CRYPTO_AKCIPHER_RSA:\n+\t\t\terr = prepare_asym_rsa_op(vcrypto, op, vc_req_out,\n+\t\t\t\t\t&req, desc, max_n_descs);\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (unlikely(err != 0)) {\n+\t\t\tVC_LOG_ERR(\"Failed to process asym request\");\n+\t\t\tgoto error_exit;\n+\t\t}\n+\n \t\tbreak;\n \tdefault:\n \t\terr = VIRTIO_CRYPTO_ERR;\n@@ -1293,12 +1732,22 @@ static __rte_always_inline struct vhost_virtqueue *\n vhost_crypto_finalize_one_request(struct rte_crypto_op *op,\n \t\tstruct vhost_virtqueue *old_vq)\n {\n-\tstruct rte_mbuf *m_src = op->sym->m_src;\n-\tstruct rte_mbuf *m_dst = op->sym->m_dst;\n-\tstruct vhost_crypto_data_req *vc_req = rte_mbuf_to_priv(m_src);\n+\tstruct rte_mbuf *m_src = NULL, *m_dst = NULL;\n+\tstruct vhost_crypto_data_req *vc_req;\n \tstruct vhost_virtqueue *vq;\n \tuint16_t used_idx, desc_idx;\n \n+\tif (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {\n+\t\tm_src = op->sym->m_src;\n+\t\tm_dst = op->sym->m_dst;\n+\t\tvc_req = rte_mbuf_to_priv(m_src);\n+\t} else if (op->type == RTE_CRYPTO_OP_TYPE_ASYMMETRIC) {\n+\t\tvc_req = rte_cryptodev_asym_session_get_user_data(op->asym->session);\n+\t} else {\n+\t\tVC_LOG_ERR(\"Invalid crypto op type\");\n+\t\treturn NULL;\n+\t}\n+\n \tif (unlikely(!vc_req)) {\n \t\tVC_LOG_ERR(\"Failed to retrieve vc_req\");\n \t\treturn NULL;\n@@ -1320,25 +1769,36 @@ vhost_crypto_finalize_one_request(struct rte_crypto_op *op,\n \tvq->used->ring[desc_idx].id = vq->avail->ring[desc_idx];\n \tvq->used->ring[desc_idx].len = vc_req->len;\n \n-\trte_mempool_put(m_src->pool, (void *)m_src);\n-\n-\tif (m_dst)\n-\t\trte_mempool_put(m_dst->pool, (void *)m_dst);\n+\tif (op->type == RTE_CRYPTO_OP_TYPE_SYMMETRIC) {\n+\t\trte_mempool_put(m_src->pool, (void *)m_src);\n+\t\tif (m_dst)\n+\t\t\trte_mempool_put(m_dst->pool, (void *)m_dst);\n+\t}\n \n \treturn vc_req->vq;\n }\n \n static __rte_always_inline uint16_t\n-vhost_crypto_complete_one_vm_requests(struct rte_crypto_op **ops,\n+vhost_crypto_complete_one_vm_requests(int vid, int qid, struct rte_crypto_op **ops,\n \t\tuint16_t nb_ops, int *callfd)\n {\n+\tstruct virtio_net *dev = get_device(vid);\n \tuint16_t processed = 1;\n \tstruct vhost_virtqueue *vq, *tmp_vq;\n \n+\tif (unlikely(dev == NULL)) {\n+\t\tVC_LOG_ERR(\"Invalid vid %i\", vid);\n+\t\treturn 0;\n+\t}\n+\n \tif (unlikely(nb_ops == 0))\n \t\treturn 0;\n \n-\tvq = vhost_crypto_finalize_one_request(ops[0], NULL);\n+\trte_spinlock_lock(&dev->virtqueue_lock);\n+\ttmp_vq = dev->virtqueue[qid];\n+\trte_spinlock_unlock(&dev->virtqueue_lock);\n+\n+\tvq = vhost_crypto_finalize_one_request(ops[0], tmp_vq);\n \tif (unlikely(vq == NULL))\n \t\treturn 0;\n \ttmp_vq = vq;\n@@ -1383,7 +1843,7 @@ rte_vhost_crypto_driver_start(const char *path)\n \n int\n rte_vhost_crypto_create(int vid, uint8_t cryptodev_id,\n-\t\tstruct rte_mempool *sess_pool,\n+\t\tstruct rte_mempool *sym_sess_pool, struct rte_mempool *asym_sess_pool,\n \t\tint socket_id)\n {\n \tstruct virtio_net *dev = get_device(vid);\n@@ -1404,9 +1864,11 @@ rte_vhost_crypto_create(int vid, uint8_t cryptodev_id,\n \t\treturn -ENOMEM;\n \t}\n \n-\tvcrypto->sess_pool = sess_pool;\n+\tvcrypto->sym_sess_pool = sym_sess_pool;\n+\tvcrypto->asym_sess_pool = asym_sess_pool;\n \tvcrypto->cid = cryptodev_id;\n-\tvcrypto->cache_session_id = UINT64_MAX;\n+\tvcrypto->cache_sym_session_id = UINT64_MAX;\n+\tvcrypto->cache_asym_session_id = UINT64_MAX;\n \tvcrypto->last_session_id = 1;\n \tvcrypto->dev = dev;\n \tvcrypto->option = RTE_VHOST_CRYPTO_ZERO_COPY_DISABLE;\n@@ -1577,7 +2039,12 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,\n \t\treturn 0;\n \t}\n \n+\trte_spinlock_lock(&dev->virtqueue_lock);\n \tvq = dev->virtqueue[qid];\n+\trte_spinlock_unlock(&dev->virtqueue_lock);\n+\n+\tif (!vq || !vq->avail)\n+\t\treturn 0;\n \n \tavail_idx = *((volatile uint16_t *)&vq->avail->idx);\n \tstart_idx = vq->last_used_idx;\n@@ -1659,7 +2126,7 @@ rte_vhost_crypto_fetch_requests(int vid, uint32_t qid,\n }\n \n uint16_t\n-rte_vhost_crypto_finalize_requests(struct rte_crypto_op **ops,\n+rte_vhost_crypto_finalize_requests(int vid, int qid, struct rte_crypto_op **ops,\n \t\tuint16_t nb_ops, int *callfds, uint16_t *nb_callfds)\n {\n \tstruct rte_crypto_op **tmp_ops = ops;\n@@ -1668,7 +2135,7 @@ rte_vhost_crypto_finalize_requests(struct rte_crypto_op **ops,\n \tuint16_t idx = 0;\n \n \twhile (left) {\n-\t\tcount = vhost_crypto_complete_one_vm_requests(tmp_ops, left,\n+\t\tcount = vhost_crypto_complete_one_vm_requests(vid, qid, tmp_ops, left,\n \t\t\t\t&callfd);\n \t\tif (unlikely(count == 0))\n \t\t\tbreak;\ndiff --git a/lib/vhost/vhost_user.c b/lib/vhost/vhost_user.c\nindex 901a80bbaa..709a1df70d 100644\n--- a/lib/vhost/vhost_user.c\n+++ b/lib/vhost/vhost_user.c\n@@ -396,7 +396,9 @@ vhost_user_set_features(struct virtio_net **pdev,\n \t\t\tif (!vq)\n \t\t\t\tcontinue;\n \n+\t\t\trte_spinlock_lock(&dev->virtqueue_lock);\n \t\t\tdev->virtqueue[dev->nr_vring] = NULL;\n+\t\t\trte_spinlock_unlock(&dev->virtqueue_lock);\n \t\t\tcleanup_vq(vq, 1);\n \t\t\tcleanup_vq_inflight(dev, vq);\n \t\t\t/* vhost_user_lock_all_queue_pairs locked all qps */\n@@ -540,7 +542,9 @@ numa_realloc(struct virtio_net **pdev, struct vhost_virtqueue **pvq)\n \n \tif (vq != dev->virtqueue[vq->index]) {\n \t\tVHOST_LOG_CONFIG(dev->ifname, INFO, \"reallocated virtqueue on node %d\\n\", node);\n+\t\trte_spinlock_lock(&dev->virtqueue_lock);\n \t\tdev->virtqueue[vq->index] = vq;\n+\t\trte_spinlock_unlock(&dev->virtqueue_lock);\n \t}\n \n \tif (vq_is_packed(dev)) {\ndiff --git a/lib/vhost/vhost_user.h b/lib/vhost/vhost_user.h\nindex edf7adb3c0..6174f32dcf 100644\n--- a/lib/vhost/vhost_user.h\n+++ b/lib/vhost/vhost_user.h\n@@ -99,11 +99,10 @@ typedef struct VhostUserLog {\n /* Comply with Cryptodev-Linux */\n #define VHOST_USER_CRYPTO_MAX_HMAC_KEY_LENGTH\t512\n #define VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH\t64\n+#define VHOST_USER_CRYPTO_MAX_KEY_LENGTH\t1024\n \n /* Same structure as vhost-user backend session info */\n-typedef struct VhostUserCryptoSessionParam {\n-\tint64_t session_id;\n-\tuint32_t op_code;\n+typedef struct VhostUserCryptoSymSessionParam {\n \tuint32_t cipher_algo;\n \tuint32_t cipher_key_len;\n \tuint32_t hash_algo;\n@@ -114,10 +113,37 @@ typedef struct VhostUserCryptoSessionParam {\n \tuint8_t dir;\n \tuint8_t hash_mode;\n \tuint8_t chaining_dir;\n-\tuint8_t *ciphe_key;\n+\tuint8_t *cipher_key;\n \tuint8_t *auth_key;\n \tuint8_t cipher_key_buf[VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH];\n \tuint8_t auth_key_buf[VHOST_USER_CRYPTO_MAX_HMAC_KEY_LENGTH];\n+} VhostUserCryptoSymSessionParam;\n+\n+\n+typedef struct VhostUserCryptoAsymRsaParam {\n+\tuint32_t padding_algo;\n+\tuint32_t hash_algo;\n+\tuint8_t private_key_type;\n+} VhostUserCryptoAsymRsaParam;\n+\n+typedef struct VhostUserCryptoAsymSessionParam {\n+\tuint32_t algo;\n+\tuint32_t key_type;\n+\tuint32_t key_len;\n+\tuint8_t *key;\n+\tunion {\n+\t\tVhostUserCryptoAsymRsaParam rsa;\n+\t} u;\n+\tuint8_t key_buf[VHOST_USER_CRYPTO_MAX_KEY_LENGTH];\n+} VhostUserCryptoAsymSessionParam;\n+\n+typedef struct VhostUserCryptoSessionParam {\n+\tuint32_t op_code;\n+\tunion {\n+\t\tVhostUserCryptoSymSessionParam sym_sess;\n+\t\tVhostUserCryptoAsymSessionParam asym_sess;\n+\t} u;\n+\tuint64_t session_id;\n } VhostUserCryptoSessionParam;\n \n typedef struct VhostUserVringArea {\ndiff --git a/lib/vhost/virtio_crypto.h b/lib/vhost/virtio_crypto.h\nindex e3b93573c8..703a059768 100644\n--- a/lib/vhost/virtio_crypto.h\n+++ b/lib/vhost/virtio_crypto.h\n@@ -9,6 +9,7 @@\n #define VIRTIO_CRYPTO_SERVICE_HASH   1\n #define VIRTIO_CRYPTO_SERVICE_MAC    2\n #define VIRTIO_CRYPTO_SERVICE_AEAD   3\n+#define VIRTIO_CRYPTO_SERVICE_AKCIPHER 4\n \n #define VIRTIO_CRYPTO_OPCODE(service, op)   (((service) << 8) | (op))\n \n@@ -29,6 +30,10 @@ struct virtio_crypto_ctrl_header {\n \t   VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x02)\n #define VIRTIO_CRYPTO_AEAD_DESTROY_SESSION \\\n \t   VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x03)\n+#define VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION \\\n+\t   VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x04)\n+#define VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION \\\n+\t   VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x05)\n \tuint32_t opcode;\n \tuint32_t algo;\n \tuint32_t flag;\n@@ -152,6 +157,63 @@ struct virtio_crypto_aead_create_session_req {\n \tuint8_t padding[32];\n };\n \n+struct virtio_crypto_rsa_session_para {\n+#define VIRTIO_CRYPTO_RSA_RAW_PADDING   0\n+#define VIRTIO_CRYPTO_RSA_PKCS1_PADDING 1\n+\tuint32_t padding_algo;\n+\n+#define VIRTIO_CRYPTO_RSA_NO_HASH   0\n+#define VIRTIO_CRYPTO_RSA_MD2       1\n+#define VIRTIO_CRYPTO_RSA_MD3       2\n+#define VIRTIO_CRYPTO_RSA_MD4       3\n+#define VIRTIO_CRYPTO_RSA_MD5       4\n+#define VIRTIO_CRYPTO_RSA_SHA1      5\n+#define VIRTIO_CRYPTO_RSA_SHA256    6\n+#define VIRTIO_CRYPTO_RSA_SHA384    7\n+#define VIRTIO_CRYPTO_RSA_SHA512    8\n+#define VIRTIO_CRYPTO_RSA_SHA224    9\n+\tuint32_t hash_algo;\n+\n+#define VIRTIO_CRYPTO_RSA_PRIVATE_KEY_UNKNOWN 0\n+#define VIRTIO_CRYPTO_RSA_PRIVATE_KEY_EXP     1\n+#define VIRTIO_CRYPTO_RSA_PRIVATE_KEY_QT      2\n+\tuint8_t private_key_type;\n+};\n+\n+struct virtio_crypto_ecdsa_session_para {\n+#define VIRTIO_CRYPTO_CURVE_UNKNOWN   0\n+#define VIRTIO_CRYPTO_CURVE_NIST_P192 1\n+#define VIRTIO_CRYPTO_CURVE_NIST_P224 2\n+#define VIRTIO_CRYPTO_CURVE_NIST_P256 3\n+#define VIRTIO_CRYPTO_CURVE_NIST_P384 4\n+#define VIRTIO_CRYPTO_CURVE_NIST_P521 5\n+\tuint32_t curve_id;\n+\tuint32_t padding;\n+};\n+\n+struct virtio_crypto_akcipher_session_para {\n+#define VIRTIO_CRYPTO_NO_AKCIPHER    0\n+#define VIRTIO_CRYPTO_AKCIPHER_RSA   1\n+#define VIRTIO_CRYPTO_AKCIPHER_DSA   2\n+#define VIRTIO_CRYPTO_AKCIPHER_ECDSA 3\n+\tuint32_t algo;\n+\n+#define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC  1\n+#define VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE 2\n+\tuint32_t keytype;\n+\tuint32_t keylen;\n+\n+\tunion {\n+\t\tstruct virtio_crypto_rsa_session_para rsa;\n+\t\tstruct virtio_crypto_ecdsa_session_para ecdsa;\n+\t} u;\n+};\n+\n+struct virtio_crypto_akcipher_create_session_req {\n+\tstruct virtio_crypto_akcipher_session_para para;\n+\tuint8_t padding[36];\n+};\n+\n struct virtio_crypto_alg_chain_session_para {\n #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER  1\n #define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH  2\n@@ -219,6 +281,8 @@ struct virtio_crypto_op_ctrl_req {\n \t\t\tmac_create_session;\n \t\tstruct virtio_crypto_aead_create_session_req\n \t\t\taead_create_session;\n+\t\tstruct virtio_crypto_akcipher_create_session_req\n+\t\t\takcipher_create_session;\n \t\tstruct virtio_crypto_destroy_session_req\n \t\t\tdestroy_session;\n \t\tuint8_t padding[56];\n@@ -238,6 +302,14 @@ struct virtio_crypto_op_header {\n \tVIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x00)\n #define VIRTIO_CRYPTO_AEAD_DECRYPT \\\n \tVIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x01)\n+#define VIRTIO_CRYPTO_AKCIPHER_ENCRYPT \\\n+\tVIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x00)\n+#define VIRTIO_CRYPTO_AKCIPHER_DECRYPT \\\n+\tVIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x01)\n+#define VIRTIO_CRYPTO_AKCIPHER_SIGN \\\n+\tVIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x02)\n+#define VIRTIO_CRYPTO_AKCIPHER_VERIFY \\\n+\tVIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AKCIPHER, 0x03)\n \tuint32_t opcode;\n \t/* algo should be service-specific algorithms */\n \tuint32_t algo;\n@@ -362,6 +434,16 @@ struct virtio_crypto_aead_data_req {\n \tuint8_t padding[32];\n };\n \n+struct virtio_crypto_akcipher_para {\n+\tuint32_t src_data_len;\n+\tuint32_t dst_data_len;\n+};\n+\n+struct virtio_crypto_akcipher_data_req {\n+\tstruct virtio_crypto_akcipher_para para;\n+\tuint8_t padding[40];\n+};\n+\n /* The request of the data virtqueue's packet */\n struct virtio_crypto_op_data_req {\n \tstruct virtio_crypto_op_header header;\n@@ -371,6 +453,7 @@ struct virtio_crypto_op_data_req {\n \t\tstruct virtio_crypto_hash_data_req hash_req;\n \t\tstruct virtio_crypto_mac_data_req mac_req;\n \t\tstruct virtio_crypto_aead_data_req aead_req;\n+\t\tstruct virtio_crypto_akcipher_data_req akcipher_req;\n \t\tuint8_t padding[48];\n \t} u;\n };\n@@ -380,6 +463,8 @@ struct virtio_crypto_op_data_req {\n #define VIRTIO_CRYPTO_BADMSG    2\n #define VIRTIO_CRYPTO_NOTSUPP   3\n #define VIRTIO_CRYPTO_INVSESS   4 /* Invalid session id */\n+#define VIRTIO_CRYPTO_NOSPC     5 /* no free session ID */\n+#define VIRTIO_CRYPTO_KEY_REJECTED 6 /* Signature verification failed */\n \n /* The accelerator hardware is ready */\n #define VIRTIO_CRYPTO_S_HW_READY  (1 << 0)\n@@ -410,7 +495,7 @@ struct virtio_crypto_config {\n \tuint32_t max_cipher_key_len;\n \t/* Maximum length of authenticated key */\n \tuint32_t max_auth_key_len;\n-\tuint32_t reserve;\n+\tuint32_t akcipher_algo;\n \t/* Maximum size of each crypto request's content */\n \tuint64_t max_size;\n };\n",
    "prefixes": [
        "RFC",
        "3/6"
    ]
}