From: "Longpeng (Mike)" <longpeng2@huawei.com>
To: Halil Pasic <pasic@linux.vnet.ibm.com>
Cc: qemu-devel@nongnu.org, virtio-dev@lists.oasis-open.org,
weidong.huang@huawei.com, mst@redhat.com, jasowang@redhat.com,
john.griffin@intel.com, Varun.Sethi@freescale.com,
denglingli@chinamobile.com, arei.gonglei@hotmail.com,
agraf@suse.de, arei.gonglei@huawei.com, vincent.jardin@6wind.com,
Ola.Liljedahl@arm.com, luonengjun@huawei.com, xin.zeng@intel.com,
liang.j.ma@intel.com, stefanha@redhat.com,
Jani.Kokkonen@huawei.com, brian.a.keating@intel.com,
wangxinxin.wang@huawei.com, cohuck@redhat.com,
mike.caraman@nxp.com
Subject: Re: [Qemu-devel] [virtio-dev] Re: [RFC 0/8] virtio-crypto: add multiplexing mode support
Date: Thu, 14 Sep 2017 08:58:33 +0800 [thread overview]
Message-ID: <59B9D439.10807@huawei.com> (raw)
In-Reply-To: <2d8ae3d3-438b-da84-4959-cf63f4f4ce99@linux.vnet.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 2732 bytes --]
On 2017/9/14 2:14, Halil Pasic wrote:
>
>
> On 09/11/2017 03:10 AM, Longpeng(Mike) wrote:
>> *NOTE*
>> The code realization is based on the latest virtio crypto spec:
>> [PATCH v19 0/2] virtio-crypto: virtio crypto device specification
>> https://lists.nongnu.org/archive/html/qemu-devel/2017-08/msg05217.html
>>
>> In session mode, the process of create/close a session
>> makes we have a least one full round-trip cost from guest to host to guest
>> to be able to send any data for symmetric algorithms. It gets ourself into
>> synchronization troubles in some scenarios like a web server handling lots
>> of small requests whose algorithms and keys are different.
>>
>> We can support one-blob request (no sessions) as well for symmetric
>> algorithms, including HASH, MAC services. The benefit is obvious for
>> HASH service because it's usually a one-blob operation.
>>
>
> Hi!
>
> I've just started looking at this. Patch #1 modifies linux/virtio_crypto.h
> which if I compare with the (almost) latest linux master is different. Thus
> I would expect a corresponding kernel patch set too, but I haven't received
> one, nor did I find a reference in the cover letter.
>
> I think if I want to test the new features I need the kernel counter-part
> too, or?
>
> Could you point me to the kernel counterpart?
>
Hi Halil,
We haven't implemented the kernel frontend part yet, but there's a testcase
based on qtest, you can use it.
Please see the attachment.
--
Regards,
Longpeng(Mike)
> Regards,
> Halil
>
>
>> Gonglei (3):
>> virtio-crypto: add stateless crypto request handler
>> cryptodev: extract one util function
>> virtio-crypto: add host feature bits support
>>
>> Longpeng(Mike) (5):
>> virtio-crypto: add new definations for multiplexing mode
>> virtio-crypto: add session creation logic for mux mode
>> virtio-crypto: add dataq operation logic for mux mode
>> cryptodev: add stateless mode cipher support
>> cryptodev-builtin: add stateless cipher support
>>
>> backends/cryptodev-builtin.c | 189 ++++++++---
>> backends/cryptodev.c | 21 ++
>> hw/virtio/virtio-crypto.c | 433 +++++++++++++++++++++++--
>> include/hw/virtio/virtio-crypto.h | 2 +
>> include/standard-headers/linux/virtio_crypto.h | 182 ++++++++++-
>> include/sysemu/cryptodev.h | 21 ++
>> 6 files changed, 774 insertions(+), 74 deletions(-)
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: virtio-dev-unsubscribe@lists.oasis-open.org
> For additional commands, e-mail: virtio-dev-help@lists.oasis-open.org
>
>
> .
>
--
Regards,
Longpeng(Mike)
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: testcase.patch --]
[-- Type: text/plain; charset="gb18030"; name="testcase.patch", Size: 24223 bytes --]
From 259359700b1847cd66f9c3e04a86a14546f6f0e0 Mon Sep 17 00:00:00 2001
From: Gonglei <arei.gonglei@huawei.com>
Date: Mon, 8 May 2017 13:42:53 +0800
Subject: [PATCH] qtest: emulate virtio crypto as a legacy device for
experiment
Because the current qtest framework do not support virtio-1
or latter devices. For experimental purpose,
let's emulate the virtio crypto device as a legacy virtio
device by default. Using 0x1014 as virtio crypto pci device ID
because virtio crypto ID is 20 (0x14).
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
virtio-crypto-test: add qtest case for virtio-crypto
We can simply test the functions of virtio crypto
device, including session creation, session closing,
cipher encryption and decryption.
Quick usage:
# make tests/virtio-crypto-test && ./tests/virtio-crypto-test
CC tests/virtio-crypto-test.o
LINK tests/virtio-crypto-test
/virtio/crypto/cbc(aes-128-session-mode): OK
/virtio/crypto/cbc(aes-128-stateless-mode): OK
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
[rebase on the v19 spec]
Signed-off-by: Longpeng(Mike) <longpeng2@huawei.com>
---
docs/specs/pci-ids.txt | 2 +
hw/virtio/virtio-crypto-pci.c | 4 +-
include/hw/pci/pci.h | 2 +
tests/Makefile.include | 3 +
tests/virtio-crypto-test.c | 600 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 610 insertions(+), 1 deletion(-)
create mode 100644 tests/virtio-crypto-test.c
diff --git a/docs/specs/pci-ids.txt b/docs/specs/pci-ids.txt
index bb99a02..61877b7 100755
--- a/docs/specs/pci-ids.txt
+++ b/docs/specs/pci-ids.txt
@@ -22,6 +22,7 @@ maintained as part of the virtio specification.
1af4:1004 SCSI host bus adapter device (legacy)
1af4:1005 entropy generator device (legacy)
1af4:1009 9p filesystem device (legacy)
+1af4:1014 crypto device (legacy)
1af4:1041 network device (modern)
1af4:1042 block device (modern)
@@ -32,6 +33,7 @@ maintained as part of the virtio specification.
1af4:1049 9p filesystem device (modern)
1af4:1050 virtio gpu device (modern)
1af4:1052 virtio input device (modern)
+1af4:1054 crypto device (modern)
1af4:10f0 Available for experimental usage without registration. Must get
to official ID when the code leaves the test lab (i.e. when seeking
diff --git a/hw/virtio/virtio-crypto-pci.c b/hw/virtio/virtio-crypto-pci.c
index bf64996..66a2966 100755
--- a/hw/virtio/virtio-crypto-pci.c
+++ b/hw/virtio/virtio-crypto-pci.c
@@ -37,7 +37,6 @@ static void virtio_crypto_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
}
qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
- virtio_pci_force_virtio_1(vpci_dev);
object_property_set_bool(OBJECT(vdev), true, "realized", errp);
object_property_set_link(OBJECT(vcrypto),
OBJECT(vcrypto->vdev.conf.cryptodev), "cryptodev",
@@ -53,6 +52,9 @@ static void virtio_crypto_pci_class_init(ObjectClass *klass, void *data)
k->realize = virtio_crypto_pci_realize;
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
dc->props = virtio_crypto_pci_properties;
+ pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_CRYPTO;
+ pcidev_k->revision = 0;
pcidev_k->class_id = PCI_CLASS_OTHERS;
}
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index e598b09..ae9327c 100755
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -83,6 +83,8 @@
#define PCI_DEVICE_ID_VIRTIO_RNG 0x1005
#define PCI_DEVICE_ID_VIRTIO_9P 0x1009
#define PCI_DEVICE_ID_VIRTIO_VSOCK 0x1012
+#define PCI_DEVICE_ID_VIRTIO_CRYPTO 0x1014
+
#define PCI_VENDOR_ID_REDHAT 0x1b36
#define PCI_DEVICE_ID_REDHAT_BRIDGE 0x0001
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 37c1bed..9b6c131 100755
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -192,6 +192,8 @@ check-qtest-virtio-y += tests/virtio-serial-test$(EXESUF)
gcov-files-virtio-y += i386-softmmu/hw/char/virtio-serial-bus.c
check-qtest-virtio-y += $(check-qtest-virtioserial-y)
gcov-files-virtio-y += $(gcov-files-virtioserial-y)
+check-qtest-virtio-y += tests/virtio-crypto-test$(EXESUF)
+gcov-files-virtio-y += i386-softmmu/hw/virtio/virtio-crypto.c
check-qtest-pci-y += tests/e1000-test$(EXESUF)
gcov-files-pci-y += hw/net/e1000.c
@@ -753,6 +755,7 @@ tests/virtio-scsi-test$(EXESUF): tests/virtio-scsi-test.o $(libqos-virtio-obj-y)
tests/virtio-9p-test$(EXESUF): tests/virtio-9p-test.o $(libqos-virtio-obj-y)
tests/virtio-serial-test$(EXESUF): tests/virtio-serial-test.o
tests/virtio-console-test$(EXESUF): tests/virtio-console-test.o
+tests/virtio-crypto-test$(EXESUF): tests/virtio-crypto-test.o $(libqos-virtio-obj-y)
tests/tpci200-test$(EXESUF): tests/tpci200-test.o
tests/display-vga-test$(EXESUF): tests/display-vga-test.o
tests/ipoctal232-test$(EXESUF): tests/ipoctal232-test.o
diff --git a/tests/virtio-crypto-test.c b/tests/virtio-crypto-test.c
new file mode 100644
index 0000000..8825f1f
--- /dev/null
+++ b/tests/virtio-crypto-test.c
@@ -0,0 +1,600 @@
+/*
+ * QTest testcase for VirtIO Crypto Device
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ * Gonglei <arei.gonglei@huawei.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <stdlib.h>
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "libqos/virtio.h"
+#include "libqos/virtio-pci.h"
+#include "libqos/virtio-mmio.h"
+#include "libqos/pci-pc.h"
+#include "libqos/malloc.h"
+#include "libqos/malloc-pc.h"
+#include "libqos/malloc-generic.h"
+#include "qemu/bswap.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_ring.h"
+#include "standard-headers/linux/virtio_crypto.h"
+#include "standard-headers/linux/virtio_pci.h"
+
+#define QVIRTIO_CRYPTO_TIMEOUT_US (30 * 1000 * 1000)
+
+#define PCI_SLOT_HP 0x06
+#define PCI_SLOT 0x04
+#define PCI_FN 0x00
+
+/*
+ * VirtIOCryptoCipherTestData: structure to describe a cipher test
+ * @key: A pointer to a key used by the test
+ * @key_len: The length of @key
+ * @iv: A pointer to the IV/Counter used by the test
+ * @iv_len: The length of @iv
+ * @input: A pointer to data used as input
+ * @ilen The length of data in @input
+ * @output: A pointer to what the test need to produce
+ * @olen: The length of data in @output
+ * @algo: The type of algorithm, refer to VIRTIO_CRYPTO_CIPHER_AES_*
+ */
+typedef struct VirtIOCryptoCipherTestData {
+ const char *path;
+ unsigned short algo;
+ const char *key;
+ const char *iv;
+ const char *input;
+ const char *output;
+ unsigned char key_len;
+ unsigned char iv_len;
+ unsigned short ilen;
+ unsigned short olen;
+ bool is_statelss_mode;
+} VirtIOCryptoCipherTestData;
+
+
+static VirtIOCryptoCipherTestData cipher_test_data[] = {
+ { /* From RFC 3602 */
+ .path = "/virtio/crypto/cbc(aes-128-session-mode)",
+ .algo = VIRTIO_CRYPTO_CIPHER_AES_CBC,
+ .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .key_len = 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .iv_len = 16,
+ .input = "Single block msg",
+ .ilen = 16,
+ .output = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
+ .olen = 16,
+ .is_statelss_mode = false,
+ },
+ { /* From RFC 3602 */
+ .path = "/virtio/crypto/cbc(aes-128-stateless-mode)",
+ .algo = VIRTIO_CRYPTO_CIPHER_AES_CBC,
+ .key = "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
+ "\x51\x2e\x03\xd5\x34\x12\x00\x06",
+ .key_len = 16,
+ .iv = "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
+ "\xb4\x22\xda\x80\x2c\x9f\xac\x41",
+ .iv_len = 16,
+ .input = "Single block msg",
+ .ilen = 16,
+ .output = "\xe3\x53\x77\x9c\x10\x79\xae\xb8"
+ "\x27\x08\x94\x2d\xbe\x77\x18\x1a",
+ .olen = 16,
+ .is_statelss_mode = true,
+ },
+};
+
+static QPCIBus *virtio_crypto_test_start(void)
+{
+ char *cmdline;
+
+ cmdline = g_strdup_printf(
+ "-object cryptodev-backend-builtin,id=cryptodev0 "
+ "-device virtio-crypto-pci,id=crypto0,"
+ "cryptodev=cryptodev0");
+
+ qtest_start(cmdline);
+ g_free(cmdline);
+
+ return qpci_init_pc(NULL);
+}
+
+static void test_end(void)
+{
+ qtest_end();
+}
+
+static QVirtioPCIDevice *virtio_crypto_pci_init(QPCIBus *bus, int slot)
+{
+ QVirtioPCIDevice *dev;
+
+ dev = qvirtio_pci_device_find(bus, VIRTIO_ID_CRYPTO);
+ g_assert(dev != NULL);
+ g_assert_cmphex(dev->vdev.device_type, ==, VIRTIO_ID_CRYPTO);
+
+ qvirtio_pci_device_enable(dev);
+ qvirtio_reset(&dev->vdev);
+ qvirtio_set_acknowledge(&dev->vdev);
+ qvirtio_set_driver(&dev->vdev);
+
+ return dev;
+}
+
+static uint64_t
+virtio_crypto_ctrl_request(QGuestAllocator *alloc,
+ struct virtio_crypto_op_ctrl_req *req)
+{
+ uint64_t addr;
+
+ addr = guest_alloc(alloc, sizeof(*req));
+
+ memwrite(addr, req, sizeof(*req));
+
+ return addr;
+}
+
+static uint64_t
+virtio_crypto_data_request(QGuestAllocator *alloc,
+ struct virtio_crypto_op_data_req *req)
+{
+ uint64_t addr;
+
+ addr = guest_alloc(alloc, sizeof(*req));
+
+ memwrite(addr, req, sizeof(*req));
+
+ return addr;
+}
+
+static void
+virtio_crypto_driver_init(QVirtioDevice *dev)
+{
+ /* Read configure space to get supported crypto services */
+
+ qvirtio_set_driver_ok(dev);
+}
+
+static uint64_t
+virtio_crypto_create_session(QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *vq,
+ VirtIOCryptoCipherTestData *data,
+ int encrypt)
+{
+ uint32_t free_head;
+ struct virtio_crypto_op_ctrl_req ctrl;
+ struct virtio_crypto_session_input input;
+ uint32_t key_len = data->key_len;
+ uint64_t req_addr;
+ uint64_t key_addr, input_addr; /* cipher key guest physical address */
+ uint64_t session_id;
+ QVRingIndirectDesc *indirect;
+
+ /* Create an encryption session */
+ ctrl.header.opcode = VIRTIO_CRYPTO_CIPHER_CREATE_SESSION;
+ ctrl.header.algo = data->algo;
+ /* Set the default dataqueue id to 0 */
+ ctrl.header.queue_id = 0;
+
+ /* Pad cipher's parameters */
+ ctrl.u.sym_create_session.op_type = VIRTIO_CRYPTO_SYM_OP_CIPHER;
+ ctrl.u.sym_create_session.u.cipher.para.algo = ctrl.header.algo;
+ ctrl.u.sym_create_session.u.cipher.para.keylen = key_len;
+ if (encrypt) {
+ ctrl.u.sym_create_session.u.cipher.para.op = VIRTIO_CRYPTO_OP_ENCRYPT;
+ } else {
+ ctrl.u.sym_create_session.u.cipher.para.op = VIRTIO_CRYPTO_OP_DECRYPT;
+ }
+
+ req_addr = virtio_crypto_ctrl_request(alloc, &ctrl);
+
+ /* Pad cipher's output data */
+ key_addr = guest_alloc(alloc, key_len);
+ memwrite(key_addr, data->key, key_len);
+
+ input.status = VIRTIO_CRYPTO_ERR;
+ input_addr = guest_alloc(alloc, sizeof(input));
+ memwrite(input_addr, &input, sizeof(input));
+
+ indirect = qvring_indirect_desc_setup(dev, alloc, 3);
+ qvring_indirect_desc_add(indirect, req_addr, sizeof(ctrl), false);
+ qvring_indirect_desc_add(indirect, key_addr, key_len, false);
+ qvring_indirect_desc_add(indirect, input_addr, sizeof(input), true);
+ free_head = qvirtqueue_add_indirect(vq, indirect);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_queue_isr(dev, vq, QVIRTIO_CRYPTO_TIMEOUT_US);
+
+ /* calculate the offset of input data */
+
+ memread(input_addr, &input, sizeof(input));
+
+ /* Verify the result */
+ g_assert_cmpint(input.status, ==, VIRTIO_CRYPTO_OK);
+
+ session_id = input.session_id;
+
+ g_free(indirect);
+ guest_free(alloc, input_addr);
+ guest_free(alloc, key_addr);
+ guest_free(alloc, req_addr);
+
+ return session_id;
+}
+
+static void
+virtio_crypto_close_session(QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *vq,
+ uint64_t session_id)
+{
+ uint32_t free_head;
+ struct virtio_crypto_op_ctrl_req ctrl;
+ uint64_t req_addr, status_addr;
+ uint8_t status;
+ QVRingIndirectDesc *indirect;
+
+ /* Create an encryption session */
+ ctrl.header.opcode = VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION;
+ /* Set the default dataqueue id to 0 */
+ ctrl.header.queue_id = 0;
+
+ ctrl.u.destroy_session.session_id = session_id;
+
+ req_addr = virtio_crypto_ctrl_request(alloc, &ctrl);
+
+ status_addr = guest_alloc(alloc, sizeof(status));
+ writel(status_addr, VIRTIO_CRYPTO_ERR);
+
+ indirect = qvring_indirect_desc_setup(dev, alloc, 2);
+ qvring_indirect_desc_add(indirect, req_addr, sizeof(ctrl), false);
+ qvring_indirect_desc_add(indirect, status_addr, sizeof(status), true);
+ free_head = qvirtqueue_add_indirect(vq, indirect);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_queue_isr(dev, vq, QVIRTIO_CRYPTO_TIMEOUT_US);
+
+ /* Verify the result */
+ status = readl(status_addr);
+ g_assert_cmpint(status, ==, VIRTIO_CRYPTO_OK);
+
+ g_free(indirect);
+ guest_free(alloc, req_addr);
+ guest_free(alloc, status_addr);
+}
+
+
+static void
+virtio_crypto_test_cipher_session_mode(QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *ctrlq,
+ QVirtQueue *vq, VirtIOCryptoCipherTestData *data,
+ int encrypt)
+{
+ uint32_t free_head;
+ struct virtio_crypto_op_data_req req;
+ uint64_t req_addr, status_addr;
+ uint64_t iv_addr = 0, src_addr, dst_addr;
+ uint64_t session_id;
+ char *output;
+ uint32_t src_len, dst_len;
+ uint8_t status;
+ QVRingIndirectDesc *indirect;
+ uint8_t entry_num;
+
+ /* Create a session */
+ session_id = virtio_crypto_create_session(dev, alloc,
+ ctrlq, data, encrypt);
+
+ /* Head of operation */
+ req.header.session_id = session_id;
+ if (encrypt) {
+ req.header.opcode = VIRTIO_CRYPTO_CIPHER_ENCRYPT;
+ } else {
+ req.header.opcode = VIRTIO_CRYPTO_CIPHER_DECRYPT;
+ }
+
+ req.u.sym_req.op_type = VIRTIO_CRYPTO_SYM_OP_CIPHER;
+ req.u.sym_req.u.cipher.para.iv_len = data->iv_len;
+ req.u.sym_req.u.cipher.para.src_data_len = data->ilen;
+ req.u.sym_req.u.cipher.para.dst_data_len = data->olen;
+
+ req_addr = virtio_crypto_data_request(alloc, &req);
+
+ /* IV */
+ if (data->iv_len > 0) {
+ iv_addr = guest_alloc(alloc, data->iv_len);
+ memwrite(iv_addr, data->iv, data->iv_len);
+
+ /* header + iv + src + dst + status */
+ entry_num = 5;
+ } else {
+ /* header + src + dst + status */
+ entry_num = 4;
+ }
+
+ if (encrypt) {
+ src_len = data->ilen;
+ dst_len = data->olen;
+ /* Source data is the input data which is a single buffer */
+ src_addr = guest_alloc(alloc, src_len);
+ memwrite(src_addr, data->input, src_len);
+ } else {
+ src_len = data->olen;
+ dst_len = data->ilen;
+ /* Source data is the output data which is a single buffer */
+ src_addr = guest_alloc(alloc, src_len);
+ memwrite(src_addr, data->output, src_len);
+ }
+
+ dst_addr = guest_alloc(alloc, dst_len);
+
+ status_addr = guest_alloc(alloc, sizeof(status));
+ writel(status_addr, VIRTIO_CRYPTO_ERR);
+
+ /* Allocate descripto table entries */
+ indirect = qvring_indirect_desc_setup(dev, alloc, entry_num);
+ qvring_indirect_desc_add(indirect, req_addr, sizeof(req), false);
+ if (data->iv_len > 0) {
+ qvring_indirect_desc_add(indirect, iv_addr, data->iv_len, false);
+ }
+ qvring_indirect_desc_add(indirect, src_addr, src_len, false);
+ qvring_indirect_desc_add(indirect, dst_addr, dst_len, true);
+ qvring_indirect_desc_add(indirect, status_addr, sizeof(status), true);
+ free_head = qvirtqueue_add_indirect(vq, indirect);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_queue_isr(dev, vq, QVIRTIO_CRYPTO_TIMEOUT_US);
+
+ /* Verify the result */
+ status = readl(status_addr);
+ g_assert_cmpint(status, ==, VIRTIO_CRYPTO_OK);
+
+ output = g_malloc0(dst_len);
+ memread(dst_addr, output, dst_len);
+ if (encrypt) {
+ g_assert_cmpstr(output, ==, data->output);
+ } else {
+ g_assert_cmpstr(output, ==, data->input);
+ }
+ g_free(output);
+
+ g_free(indirect);
+
+ if (data->iv_len > 0) {
+ guest_free(alloc, iv_addr);
+ }
+ guest_free(alloc, src_addr);
+ guest_free(alloc, dst_addr);
+ guest_free(alloc, req_addr);
+ guest_free(alloc, status_addr);
+
+ /* Close the session */
+ virtio_crypto_close_session(dev, alloc, ctrlq, session_id);
+}
+
+static void
+virtio_crypto_test_cipher_stateless_mode(QVirtioDevice *dev,
+ QGuestAllocator *alloc,
+ QVirtQueue *vq, VirtIOCryptoCipherTestData *data,
+ int encrypt)
+{
+ uint32_t free_head;
+ struct virtio_crypto_op_data_req_mux req;
+ struct virtio_crypto_sym_data_req_stateless para;
+ uint64_t req_addr, para_addr, status_addr;
+ uint64_t iv_addr = 0, src_addr, dst_addr, key_addr;
+ char *output;
+ uint32_t src_len, dst_len;
+ uint8_t status;
+ QVRingIndirectDesc *indirect;
+ uint8_t entry_num;
+
+ /* Head of operation */
+ req.header.flag = 0;
+ if (encrypt) {
+ req.header.opcode = VIRTIO_CRYPTO_CIPHER_ENCRYPT;
+ para.u.cipher.para.sess_para.op = VIRTIO_CRYPTO_OP_ENCRYPT;
+ } else {
+ req.header.opcode = VIRTIO_CRYPTO_CIPHER_DECRYPT;
+ para.u.cipher.para.sess_para.op = VIRTIO_CRYPTO_OP_DECRYPT;
+ }
+
+ para.op_type = VIRTIO_CRYPTO_SYM_OP_CIPHER;
+ para.u.cipher.para.sess_para.algo = data->algo;
+ para.u.cipher.para.sess_para.keylen = data->key_len;
+ para.u.cipher.para.iv_len = data->iv_len;
+ para.u.cipher.para.src_data_len = data->ilen;
+ para.u.cipher.para.dst_data_len = data->olen;
+
+ req_addr = guest_alloc(alloc, sizeof(req));
+ memwrite(req_addr, &req, sizeof(req));
+
+ para_addr = guest_alloc(alloc, sizeof(para));
+ memwrite(para_addr, ¶, sizeof(para));
+
+ g_assert(data->key_len > 0);
+ key_addr = guest_alloc(alloc, data->key_len);
+ memwrite(key_addr, data->key, data->key_len);
+
+ /* IV */
+ if (data->iv_len > 0) {
+ iv_addr = guest_alloc(alloc, data->iv_len);
+ memwrite(iv_addr, data->iv, data->iv_len);
+
+ /* header + key + iv + src + dst + status */
+ entry_num = 7;
+ } else {
+ /* header + key + src + dst + status */
+ entry_num = 6;
+ }
+
+ if (encrypt) {
+ src_len = data->ilen;
+ dst_len = data->olen;
+ /* Source data is the input data which is a single buffer */
+ src_addr = guest_alloc(alloc, src_len);
+ memwrite(src_addr, data->input, src_len);
+ } else {
+ src_len = data->olen;
+ dst_len = data->ilen;
+ /* Source data is the output data which is a single buffer */
+ src_addr = guest_alloc(alloc, src_len);
+ memwrite(src_addr, data->output, src_len);
+ }
+
+ dst_addr = guest_alloc(alloc, dst_len);
+
+ status_addr = guest_alloc(alloc, sizeof(status));
+ writel(status_addr, VIRTIO_CRYPTO_ERR);
+
+ /* Allocate desc table entries */
+ indirect = qvring_indirect_desc_setup(dev, alloc, entry_num);
+ qvring_indirect_desc_add(indirect, req_addr, sizeof(req), false);
+ qvring_indirect_desc_add(indirect, para_addr, sizeof(para), false);
+ qvring_indirect_desc_add(indirect, key_addr, data->key_len, false);
+ if (data->iv_len > 0) {
+ qvring_indirect_desc_add(indirect, iv_addr, data->iv_len, false);
+ }
+ qvring_indirect_desc_add(indirect, src_addr, src_len, false);
+ qvring_indirect_desc_add(indirect, dst_addr, dst_len, true);
+ qvring_indirect_desc_add(indirect, status_addr, sizeof(status), true);
+ free_head = qvirtqueue_add_indirect(vq, indirect);
+
+ qvirtqueue_kick(dev, vq, free_head);
+
+ qvirtio_wait_queue_isr(dev, vq, QVIRTIO_CRYPTO_TIMEOUT_US);
+
+ /* Verify the result */
+ status = readl(status_addr);
+ g_assert_cmpint(status, ==, VIRTIO_CRYPTO_OK);
+
+ output = g_malloc0(dst_len);
+ memread(dst_addr, output, dst_len);
+ if (encrypt) {
+ g_assert_cmpstr(output, ==, data->output);
+ } else {
+ g_assert_cmpstr(output, ==, data->input);
+ }
+ g_free(output);
+
+ g_free(indirect);
+ guest_free(alloc, key_addr);
+ if (data->iv_len > 0) {
+ guest_free(alloc, iv_addr);
+ }
+ guest_free(alloc, src_addr);
+ guest_free(alloc, dst_addr);
+ guest_free(alloc, para_addr);
+ guest_free(alloc, req_addr);
+ guest_free(alloc, status_addr);
+}
+
+static void
+virtio_crypto_test_cipher(QVirtioDevice *dev,
+ QGuestAllocator *alloc, QVirtQueue *ctrlq,
+ QVirtQueue *dataq, VirtIOCryptoCipherTestData *data,
+ int encrypt)
+{
+ if (!data->is_statelss_mode) {
+ virtio_crypto_test_cipher_session_mode(dev, alloc,
+ ctrlq, dataq, data, encrypt);
+ } else {
+ virtio_crypto_test_cipher_stateless_mode(dev, alloc,
+ dataq, data, encrypt);
+ }
+}
+
+static void virtio_crypto_pci_basic(void *opaque)
+{
+ VirtIOCryptoCipherTestData *test_data = opaque;
+ QVirtioPCIDevice *dev;
+ QPCIBus *bus;
+ QGuestAllocator *alloc;
+ QVirtQueuePCI *dataq, *controlq;
+ uint32_t features;
+
+ bus = virtio_crypto_test_start();
+ dev = virtio_crypto_pci_init(bus, PCI_SLOT);
+
+ alloc = pc_alloc_init();
+
+ features = qvirtio_get_features(&dev->vdev);
+ g_assert_cmphex(features & (1u << VIRTIO_RING_F_INDIRECT_DESC), !=, 0);
+
+ if (!test_data->is_statelss_mode) {
+ features = features & ~(QVIRTIO_F_BAD_FEATURE |
+ (1u << VIRTIO_RING_F_EVENT_IDX |
+ 1u << VIRTIO_CRYPTO_F_MUX_MODE |
+ 1u << VIRTIO_CRYPTO_F_CIPHER_STATELESS_MODE));
+ } else {
+ features = features & ~(QVIRTIO_F_BAD_FEATURE |
+ (1u << VIRTIO_RING_F_EVENT_IDX));
+ }
+ qvirtio_set_features(&dev->vdev, features);
+
+ dataq = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev,
+ alloc, 0);
+ controlq = (QVirtQueuePCI *)qvirtqueue_setup(&dev->vdev,
+ alloc, 1);
+
+ virtio_crypto_driver_init(&dev->vdev);
+
+ /* Step 1: Encryption */
+ virtio_crypto_test_cipher(&dev->vdev, alloc,
+ &controlq->vq, &dataq->vq,
+ test_data, 1);
+ /* Step 2: Decryption */
+ virtio_crypto_test_cipher(&dev->vdev, alloc,
+ &controlq->vq, &dataq->vq,
+ test_data, 0);
+
+ /* End test */
+ guest_free(alloc, dataq->vq.desc);
+ guest_free(alloc, controlq->vq.desc);
+ pc_alloc_uninit(alloc);
+ qvirtio_pci_device_disable(dev);
+ g_free(dev);
+ qpci_free_pc(bus);
+ test_end();
+}
+
+int main(int argc, char **argv)
+{
+ const char *qemu;
+ const char *arch;
+ int i, ret;
+
+ qemu = getenv("QTEST_QEMU_BINARY");
+ if (qemu == NULL) {
+ ret = setenv("QTEST_QEMU_BINARY",
+ "x86_64-softmmu/qemu-system-x86_64", 0);
+ g_assert(ret == 0);
+ }
+
+ arch = qtest_get_arch();
+
+ g_test_init(&argc, &argv, NULL);
+
+ if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+ for (i = 0; i < G_N_ELEMENTS(cipher_test_data); i++) {
+ g_test_add_data_func(cipher_test_data[i].path,
+ (void *)&cipher_test_data[i],
+ (GTestDataFunc)virtio_crypto_pci_basic);
+ }
+ }
+
+ return g_test_run();
+}
--
1.8.3.1
next prev parent reply other threads:[~2017-09-14 0:59 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-11 1:10 [Qemu-devel] [RFC 0/8] virtio-crypto: add multiplexing mode support Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 1/8] virtio-crypto: add new definations for multiplexing mode Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 2/8] virtio-crypto: add session creation logic for mux mode Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 3/8] virtio-crypto: add dataq operation " Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 4/8] cryptodev: add stateless mode cipher support Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 5/8] virtio-crypto: add stateless crypto request handler Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 6/8] cryptodev: extract one util function Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 7/8] cryptodev-builtin: add stateless cipher support Longpeng(Mike)
2017-09-11 1:10 ` [Qemu-devel] [RFC 8/8] virtio-crypto: add host feature bits support Longpeng(Mike)
2017-09-11 1:26 ` [Qemu-devel] [RFC 0/8] virtio-crypto: add multiplexing mode support no-reply
2017-09-13 18:14 ` Halil Pasic
2017-09-14 0:58 ` Longpeng (Mike) [this message]
2017-09-15 17:33 ` [Qemu-devel] [virtio-dev] " Halil Pasic
2017-09-18 1:17 ` [Qemu-devel] [virtio-dev] " Longpeng (Mike)
2017-10-06 14:24 ` Halil Pasic
2017-10-09 9:22 ` Gonglei (Arei)
2017-10-09 11:04 ` Halil Pasic
2017-10-09 11:17 ` Gonglei (Arei)
2017-10-10 8:35 ` Longpeng (Mike)
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=59B9D439.10807@huawei.com \
--to=longpeng2@huawei.com \
--cc=Jani.Kokkonen@huawei.com \
--cc=Ola.Liljedahl@arm.com \
--cc=Varun.Sethi@freescale.com \
--cc=agraf@suse.de \
--cc=arei.gonglei@hotmail.com \
--cc=arei.gonglei@huawei.com \
--cc=brian.a.keating@intel.com \
--cc=cohuck@redhat.com \
--cc=denglingli@chinamobile.com \
--cc=jasowang@redhat.com \
--cc=john.griffin@intel.com \
--cc=liang.j.ma@intel.com \
--cc=luonengjun@huawei.com \
--cc=mike.caraman@nxp.com \
--cc=mst@redhat.com \
--cc=pasic@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
--cc=vincent.jardin@6wind.com \
--cc=virtio-dev@lists.oasis-open.org \
--cc=wangxinxin.wang@huawei.com \
--cc=weidong.huang@huawei.com \
--cc=xin.zeng@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).