All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation
@ 2016-09-19  8:16 Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 01/10] cryptodev: introduce cryptodev backend interface Gonglei
                   ` (11 more replies)
  0 siblings, 12 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

Changes since v2:
 According to Daniel's comments:
 - drop cryptodev kernel module as a cryptodev backend
 - rename crypto stuff to cryptodev stuff
 - change some files' license to GPLv2+
 - remove cryptodev command line instead of QOM to define the cryptodev backend
 - rename all functions and structures in crypto sub-directory.
 - add full inline documentation for cryptodev.h
 And:
 - drop crypto-queue.c [Paolo]
 - merge some patches

Great thanks to Daniel and Paolo. Please review again, thanks!

Changes since v1:
 - rmmove mixed endian-ness handler for virtio-crypto device, just
   use little-endian. [mst]
 - add sg list support according virtio-crypto spec v10 (will be posted soon).
 - fix a memory leak in session handler.
 - add a feature page link in qemu.org (http://qemu-project.org/Features/VirtioCrypto)
 - fix some trivial problems, sush as 's/Since 2.7/Since 2.8/g' in qapi-schema.json
 - rebase the latest qemu master tree.


This patch series realize the framework and emulation of a new
virtio crypto device, which is similar with virtio net device.
 
 - I introduce the cryptodev backend as the client of virtio crypto device
   which can be realized by different methods, such as cryptodev-backend-gcrypt in my series,
   vhost-crypto kernel module, vhost-user etc.
 - The patch set abides by the virtio crypto speccification.
 - The virtio crypto support symmetric algorithms (including CIPHER and algorithm chainning)
   at present, except HASH, MAC and AEAD services.
 - unsupport hot plug/unplug cryptodev backend at this moment.

Firstly build QEMU with libgcrypt cryptography support. 

QEMU can then be started using the following parameters:

qemu-system-x86_64 \
    [...] \
        -object cryptodev-backend-gcrypt,id=cryptodev0 \
        -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \
    [...]

The front-end linux kernel driver (Experimental at present) is publicly accessible from:
 
   https://github.com/gongleiarei/virtio-crypto-linux-driver.git

After insmod virtio-crypto.ko, you can use cryptodev-linux test the crypto function
in the guest. For example:

linux-guest:/home/gonglei/cryptodev-linux/tests # ./cipher -
requested cipher CRYPTO_AES_CBC, got cbc(aes) with driver virtio_crypto_aes_cbc
AES Test passed
requested cipher CRYPTO_AES_CBC, got cbc(aes) with driver virtio_crypto_aes_cbc
requested cipher CRYPTO_AES_CBC, got cbc(aes) with driver virtio_crypto_aes_cbc
Test passed

QEMU code also can be accessible from:

 https://github.com/gongleiarei/qemu.git 

 branch virtio-crypto

For more information, please see:
 http://qemu-project.org/Features/VirtioCrypto


Gonglei (10):
  cryptodev: introduce cryptodev backend interface
  cryptodev: add symmetric algorithm operation stuff
  virtio-crypto: introduce virtio_crypto.h
  cryptodev: introduce gcrypt lib as a new cryptodev backend
  virtio-crypto: add virtio crypto device emulation
  virtio-crypto-pci: add virtio crypto pci support
  virtio-crypto: set capacity of algorithms supported
  virtio-crypto: add control queue handler
  virtio-crypto: add data queue processing handler
  cryptodev: introduce an unified wrapper for crypto operation

 crypto/Makefile.objs                           |   2 +
 crypto/cryptodev-gcrypt.c                      | 329 +++++++++
 crypto/cryptodev.c                             | 243 +++++++
 hw/virtio/Makefile.objs                        |   2 +
 hw/virtio/virtio-crypto-pci.c                  |  76 +++
 hw/virtio/virtio-crypto.c                      | 904 +++++++++++++++++++++++++
 hw/virtio/virtio-pci.h                         |  15 +
 include/crypto/cryptodev.h                     | 276 ++++++++
 include/hw/virtio/virtio-crypto.h              | 100 +++
 include/standard-headers/linux/virtio_crypto.h | 466 +++++++++++++
 qemu-options.hx                                |  18 +
 11 files changed, 2431 insertions(+)
 create mode 100644 crypto/cryptodev-gcrypt.c
 create mode 100644 crypto/cryptodev.c
 create mode 100644 hw/virtio/virtio-crypto-pci.c
 create mode 100644 hw/virtio/virtio-crypto.c
 create mode 100644 include/crypto/cryptodev.h
 create mode 100644 include/hw/virtio/virtio-crypto.h
 create mode 100644 include/standard-headers/linux/virtio_crypto.h

-- 
1.7.12.4

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 01/10] cryptodev: introduce cryptodev backend interface
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 02/10] cryptodev: add symmetric algorithm operation stuff Gonglei
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

cryptodev backend interface is used to realize the active work for
virtual crypto device.

This patch only add the framework, doesn't include specific operations.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 crypto/Makefile.objs       |   1 +
 crypto/cryptodev.c         | 175 +++++++++++++++++++++++++++++++++++++++++++++
 include/crypto/cryptodev.h | 145 +++++++++++++++++++++++++++++++++++++
 3 files changed, 321 insertions(+)
 create mode 100644 crypto/cryptodev.c
 create mode 100644 include/crypto/cryptodev.h

diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index a36d2d9..f7f3c4f 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -26,6 +26,7 @@ crypto-obj-y += xts.o
 crypto-obj-y += block.o
 crypto-obj-y += block-qcow.o
 crypto-obj-y += block-luks.o
+crypto-obj-y += cryptodev.o
 
 # Let the userspace emulators avoid linking gnutls/etc
 crypto-aes-obj-y = aes.o
diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c
new file mode 100644
index 0000000..658a018
--- /dev/null
+++ b/crypto/cryptodev.c
@@ -0,0 +1,175 @@
+/*
+ * QEMU Crypto Device Implement
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *    Gonglei <arei.gonglei@huawei.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "crypto/cryptodev.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qapi-types.h"
+#include "qapi-visit.h"
+#include "qemu/config-file.h"
+#include "qom/object_interfaces.h"
+
+static QTAILQ_HEAD(, QCryptoCryptoDevBackendClientState) crypto_clients;
+
+
+QCryptoCryptoDevBackendClientState *
+qcrypto_cryptodev_backend_new_client(const char *model,
+                                    const char *name)
+{
+    QCryptoCryptoDevBackendClientState *cc;
+
+    cc = g_malloc0(sizeof(QCryptoCryptoDevBackendClientState));
+    cc->model = g_strdup(model);
+    if (name) {
+        cc->name = g_strdup(name);
+    }
+
+    QTAILQ_INSERT_TAIL(&crypto_clients, cc, next);
+
+    return cc;
+}
+
+void qcrypto_cryptodev_backend_free_client(
+                  QCryptoCryptoDevBackendClientState *cc)
+{
+    QTAILQ_REMOVE(&crypto_clients, cc, next);
+    g_free(cc->name);
+    g_free(cc->model);
+    g_free(cc);
+}
+
+void qcrypto_cryptodev_backend_cleanup(
+             QCryptoCryptoDevBackend *backend,
+             Error **errp)
+{
+    QCryptoCryptoDevBackendClass *bc =
+                  QCRYPTO_CRYPTODEV_BACKEND_GET_CLASS(backend);
+
+    if (bc->cleanup) {
+        bc->cleanup(backend, errp);
+    }
+
+    backend->ready = 0;
+}
+
+static void
+qcrypto_cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
+                             void *opaque, Error **errp)
+{
+    QCryptoCryptoDevBackend *backend = QCRYPTO_CRYPTODEV_BACKEND(obj);
+    uint32_t value = backend->conf.peers.queues;
+
+    visit_type_uint32(v, name, &value, errp);
+}
+
+static void
+qcrypto_cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name,
+                             void *opaque, Error **errp)
+{
+    QCryptoCryptoDevBackend *backend = QCRYPTO_CRYPTODEV_BACKEND(obj);
+    Error *local_err = NULL;
+    uint32_t value;
+
+    visit_type_uint32(v, name, &value, &local_err);
+    if (local_err) {
+        goto out;
+    }
+    if (!value) {
+        error_setg(&local_err, "Property '%s.%s' doesn't take value '%"
+                   PRIu32 "'", object_get_typename(obj), name, value);
+        goto out;
+    }
+    backend->conf.peers.queues = value;
+out:
+    error_propagate(errp, local_err);
+}
+
+static void
+qcrypto_cryptodev_backend_complete(UserCreatable *uc, Error **errp)
+{
+    QCryptoCryptoDevBackend *backend = QCRYPTO_CRYPTODEV_BACKEND(uc);
+    QCryptoCryptoDevBackendClass *bc = QCRYPTO_CRYPTODEV_BACKEND_GET_CLASS(uc);
+    Error *local_err = NULL;
+
+    if (bc->init) {
+        bc->init(backend, &local_err);
+        if (local_err) {
+            goto out;
+        }
+    }
+    backend->ready = 1;
+    return;
+
+out:
+    backend->ready = 0;
+    error_propagate(errp, local_err);
+}
+
+static void qcrypto_cryptodev_backend_instance_init(Object *obj)
+{
+    object_property_add(obj, "queues", "int",
+                          qcrypto_cryptodev_backend_get_queues,
+                          qcrypto_cryptodev_backend_set_queues,
+                          NULL, NULL, NULL);
+    /* Initialize devices' queues property to 1 */
+    object_property_set_int(obj, 1, "queues", NULL);
+}
+
+static void qcrypto_cryptodev_backend_finalize(Object *obj)
+{
+
+}
+
+static void
+qcrypto_cryptodev_backend_class_init(ObjectClass *oc, void *data)
+{
+    UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+
+    ucc->complete = qcrypto_cryptodev_backend_complete;
+
+    QTAILQ_INIT(&crypto_clients);
+}
+
+static const TypeInfo qcrypto_cryptodev_backend_info = {
+    .name = TYPE_QCRYPTO_CRYPTODEV_BACKEND,
+    .parent = TYPE_OBJECT,
+    .instance_size = sizeof(QCryptoCryptoDevBackend),
+    .instance_init = qcrypto_cryptodev_backend_instance_init,
+    .instance_finalize = qcrypto_cryptodev_backend_finalize,
+    .class_size = sizeof(QCryptoCryptoDevBackendClass),
+    .class_init = qcrypto_cryptodev_backend_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { TYPE_USER_CREATABLE },
+        { }
+    }
+};
+
+static void
+qcrypto_cryptodev_backend_register_types(void)
+{
+    type_register_static(&qcrypto_cryptodev_backend_info);
+}
+
+type_init(qcrypto_cryptodev_backend_register_types);
diff --git a/include/crypto/cryptodev.h b/include/crypto/cryptodev.h
new file mode 100644
index 0000000..344dc91
--- /dev/null
+++ b/include/crypto/cryptodev.h
@@ -0,0 +1,145 @@
+/*
+ * QEMU Crypto Device Implement
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *    Gonglei <arei.gonglei@huawei.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+#ifndef QCRYPTO_CRYPTODEV_H
+#define QCRYPTO_CRYPTODEV_H
+
+#include "qom/object.h"
+#include "qemu-common.h"
+
+/**
+ * QCryptoCryptoDevBackend:
+ *
+ * The QCryptoCryptoDevBackend object is an interface
+ * for different cryptodev backends, which provides crypto
+ * operation wrapper.
+ *
+ */
+
+#define TYPE_QCRYPTO_CRYPTODEV_BACKEND "cryptodev-backend"
+
+#define QCRYPTO_CRYPTODEV_BACKEND(obj) \
+    OBJECT_CHECK(QCryptoCryptoDevBackend, \
+                 (obj), TYPE_QCRYPTO_CRYPTODEV_BACKEND)
+#define QCRYPTO_CRYPTODEV_BACKEND_GET_CLASS(obj) \
+    OBJECT_GET_CLASS(QCryptoCryptoDevBackendClass, \
+                 (obj), TYPE_QCRYPTO_CRYPTODEV_BACKEND)
+#define QCRYPTO_CRYPTODEV_BACKEND_CLASS(klass) \
+    OBJECT_CLASS_CHECK(QCryptoCryptoDevBackendClass, \
+                (klass), TYPE_QCRYPTO_CRYPTODEV_BACKEND)
+
+
+#define MAX_CRYPTO_QUEUE_NUM  64
+
+typedef struct QCryptoCryptoDevBackendConf QCryptoCryptoDevBackendConf;
+typedef struct QCryptoCryptoDevBackendPeers QCryptoCryptoDevBackendPeers;
+typedef struct QCryptoCryptoDevBackendClientState
+                     QCryptoCryptoDevBackendClientState;
+typedef struct QCryptoCryptoDevBackend QCryptoCryptoDevBackend;
+
+
+typedef struct QCryptoCryptoDevBackendClass {
+    ObjectClass parent_class;
+
+    void (*init)(QCryptoCryptoDevBackend *backend, Error **errp);
+    void (*cleanup)(QCryptoCryptoDevBackend *backend, Error **errp);
+} QCryptoCryptoDevBackendClass;
+
+
+struct QCryptoCryptoDevBackendClientState {
+    char *model;
+    char *name;
+    char info_str[128];
+    unsigned int queue_index;
+    QTAILQ_ENTRY(QCryptoCryptoDevBackendClientState) next;
+};
+
+struct QCryptoCryptoDevBackendPeers {
+    QCryptoCryptoDevBackendClientState *ccs[MAX_CRYPTO_QUEUE_NUM];
+    uint32_t queues;
+};
+
+struct QCryptoCryptoDevBackendConf {
+    QCryptoCryptoDevBackendPeers peers;
+
+    /* Supported service mask */
+    uint32_t crypto_services;
+
+    /* Detailed algorithms mask */
+    uint32_t cipher_algo_l;
+    uint32_t cipher_algo_h;
+    uint32_t hash_algo;
+    uint32_t mac_algo_l;
+    uint32_t mac_algo_h;
+    uint32_t asym_algo;
+    uint32_t kdf_algo;
+    uint32_t aead_algo;
+    uint32_t primitive_algo;
+};
+
+struct QCryptoCryptoDevBackend {
+    Object parent_obj;
+
+    int ready;
+    QCryptoCryptoDevBackendConf conf;
+};
+
+/**
+ * qcrypto_cryptodev_backend_new_client:
+ * @model: the cryptodev backend model
+ * @name: the cryptodev backend name, can be NULL
+ *
+ * Creates a new cryptodev backend client object
+ * with the @name in the mode @mode.
+ *
+ * The returned object must be released with
+ * qcrypto_cryptodev_backend_free_client() when no
+ * longer required
+ *
+ * Returns: a new cryptodev backend client object
+ */
+QCryptoCryptoDevBackendClientState *
+qcrypto_cryptodev_backend_new_client(const char *model,
+                                    const char *name);
+/**
+ * qcrypto_cryptodev_backend_free_client:
+ * @cc: the cryptodev backend client object
+ *
+ * Release the memory associated with @cc that
+ * was previously allocated by qcrypto_cryptodev_backend_new_client()
+ */
+void qcrypto_cryptodev_backend_free_client(
+                  QCryptoCryptoDevBackendClientState *cc);
+
+/**
+ * qcrypto_cryptodev_backend_cleanup:
+ * @backend: the cryptodev backend object
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Clean the resouce associated with @backend that realizaed
+ * by the specific backend's init() callback
+ */                  
+void qcrypto_cryptodev_backend_cleanup(
+           QCryptoCryptoDevBackend *backend,
+           Error **errp);
+
+#endif /* QCRYPTO_CRYPTODEV_H */
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 02/10] cryptodev: add symmetric algorithm operation stuff
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 01/10] cryptodev: introduce cryptodev backend interface Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 03/10] virtio-crypto: introduce virtio_crypto.h Gonglei
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

This patch add session operation and crypto operation
stuff in the cryptodev backend, including function
pointers and correpsonding structures.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 crypto/cryptodev.c         |  44 +++++++++++++++
 include/crypto/cryptodev.h | 132 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 175 insertions(+), 1 deletion(-)

diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c
index 658a018..0b3d55e 100644
--- a/crypto/cryptodev.c
+++ b/crypto/cryptodev.c
@@ -74,6 +74,50 @@ void qcrypto_cryptodev_backend_cleanup(
     backend->ready = 0;
 }
 
+int64_t qcrypto_cryptodev_backend_sym_create_session(
+           QCryptoCryptoDevBackend *backend,
+           QCryptoCryptoDevBackendSymSessionInfo *sess_info,
+           uint32_t queue_index, Error **errp)
+{
+    QCryptoCryptoDevBackendClass *bc =
+                      QCRYPTO_CRYPTODEV_BACKEND_GET_CLASS(backend);
+
+    if (bc->create_session) {
+        return bc->create_session(backend, sess_info, queue_index, errp);
+    }
+
+    return -1;
+}
+
+int qcrypto_cryptodev_backend_sym_close_session(
+           QCryptoCryptoDevBackend *backend,
+           uint64_t session_id, Error **errp)
+{
+    QCryptoCryptoDevBackendClass *bc =
+                      QCRYPTO_CRYPTODEV_BACKEND_GET_CLASS(backend);
+
+    if (bc->close_session) {
+        return bc->close_session(backend, session_id, errp);
+    }
+
+    return -1;
+}
+
+int qcrypto_cryptodev_backend_sym_operation(
+                 QCryptoCryptoDevBackend *backend,
+                 QCryptoCryptoDevBackendSymOpInfo *op_info,
+                 uint32_t queue_index, Error **errp)
+{
+    QCryptoCryptoDevBackendClass *bc =
+                      QCRYPTO_CRYPTODEV_BACKEND_GET_CLASS(backend);
+
+    if (bc->do_sym_op) {
+        return bc->do_sym_op(backend, op_info, queue_index, errp);
+    }
+
+    return -1;
+}
+
 static void
 qcrypto_cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name,
                              void *opaque, Error **errp)
diff --git a/include/crypto/cryptodev.h b/include/crypto/cryptodev.h
index 344dc91..7fcdc2f 100644
--- a/include/crypto/cryptodev.h
+++ b/include/crypto/cryptodev.h
@@ -56,12 +56,94 @@ typedef struct QCryptoCryptoDevBackendClientState
                      QCryptoCryptoDevBackendClientState;
 typedef struct QCryptoCryptoDevBackend QCryptoCryptoDevBackend;
 
+enum QCryptoCryptoDevBackendAlgType {
+    QCRYPTO_CRYPTODEV_BACKEND_ALG_SYM,
+    QCRYPTO_CRYPTODEV_BACKEND_ALG__MAX,
+};
+
+/**
+ * QCryptoCryptoDevBackendSymSessionInfo:
+ *
+ * @op_code: operation code (refer to virtio_crypto.h)
+ * @cipher_alg: algorithm type of CIPHER
+ * @key_len: byte length of cipher key
+ * @hash_alg: algorithm type of HASH/MAC
+ * @hash_result_len: byte length of HASH operation result
+ * @auth_key_len: byte length of authenticated key
+ * @add_len: byte length of additional authenticated data
+ * @op_type: operation type (refer to virtio_crypto.h)
+ * @direction: encryption or direction for CIPHER
+ * @hash_mode: HASH mode for HASH operation (refer to virtio_crypto.h)
+ * @alg_chain_order: order of algorithm chaining (CIPHER then HASH,
+ *                   or HASH then CIPHER)
+ * @cipher_key: pointer to a key of CIPHER
+ * @auth_key: pointer to an authenticated key of MAC
+ *
+ */
+typedef struct QCryptoCryptoDevBackendSymSessionInfo {
+    /* corresponding with virtio crypto spec */
+    uint32_t op_code;
+    uint32_t cipher_alg;
+    uint32_t key_len;
+    uint32_t hash_alg;
+    uint32_t hash_result_len;
+    uint32_t auth_key_len;
+    uint32_t add_len;
+    uint8_t op_type;
+    uint8_t direction;
+    uint8_t hash_mode;
+    uint8_t alg_chain_order;
+    uint8_t *cipher_key;
+    uint8_t *auth_key;
+} QCryptoCryptoDevBackendSymSessionInfo;
+
+/**
+ * QCryptoCryptoDevBackendSymOpInfo:
+ *
+ * @session_id: session index which was previously
+ *              created by qcrypto_cryptodev_backend_sym_create_session()
+ * @aad_len: byte length of additional authenticated data
+ * @iv_len: byte length of initialization vector
+ * @src_len: byte length of source data
+ * @dst_len: byte length of destination data, which is equal to
+ *           src_len + hash_result_len if HASH alg configured
+ * @op_type: operation type (refer to virtio_crypto.h)
+ * @iv: pointer to the initialization vector of CIPHER
+ * @src: pointer to the source data
+ * @dst: pointer to the destination data
+ * @dst: pointer to the additional authenticated data
+ * @data[0]: pointer to the extensional memory by one memory allocation
+ *
+ */
+typedef struct QCryptoCryptoDevBackendSymOpInfo {
+    uint64_t session_id;
+    uint32_t aad_len;
+    uint32_t iv_len;
+    uint32_t src_len;
+    /* dst_len is equal to src_len + hash_result_len if hash alg configured */
+    uint32_t dst_len;
+    uint8_t op_type; /* cipher or algo chainning */
+    uint8_t *iv;
+    uint8_t *src;
+    uint8_t *dst;
+    uint8_t *aad_data; /* additional auth data */
+    uint8_t data[0];
+} QCryptoCryptoDevBackendSymOpInfo;
 
 typedef struct QCryptoCryptoDevBackendClass {
     ObjectClass parent_class;
 
     void (*init)(QCryptoCryptoDevBackend *backend, Error **errp);
     void (*cleanup)(QCryptoCryptoDevBackend *backend, Error **errp);
+
+    int64_t (*create_session)(QCryptoCryptoDevBackend *backend,
+                       QCryptoCryptoDevBackendSymSessionInfo *sess_info,
+                       uint32_t queue_index, Error **errp);
+    int (*close_session)(QCryptoCryptoDevBackend *backend,
+                           uint64_t session_id, Error **errp);
+    int (*do_sym_op)(QCryptoCryptoDevBackend *backend,
+                     QCryptoCryptoDevBackendSymOpInfo *op_info,
+                     uint32_t queue_index, Error **errp);
 } QCryptoCryptoDevBackendClass;
 
 
@@ -137,9 +219,57 @@ void qcrypto_cryptodev_backend_free_client(
  *
  * Clean the resouce associated with @backend that realizaed
  * by the specific backend's init() callback
- */                  
+ */
 void qcrypto_cryptodev_backend_cleanup(
            QCryptoCryptoDevBackend *backend,
            Error **errp);
 
+/**
+ * qcrypto_cryptodev_backend_sym_create_session:
+ * @backend: the cryptodev backend object
+ * @sess_info: parameters needed by session creating
+ * @queue_index: queue index of cryptodev backend client
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Create a session for symmetric algorithms
+ *
+ * Returns: session id on success, or -1 on error
+ */
+int64_t qcrypto_cryptodev_backend_sym_create_session(
+           QCryptoCryptoDevBackend *backend,
+           QCryptoCryptoDevBackendSymSessionInfo *sess_info,
+           uint32_t queue_index, Error **errp);
+
+/**
+ * qcrypto_cryptodev_backend_sym_close_session:
+ * @backend: the cryptodev backend object
+ * @session_id: the session id that
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Close a session for symmetric algorithms which was previously
+ * created by qcrypto_cryptodev_backend_sym_create_session()
+ *
+ * Returns: 0 on success, or Negative on error
+ */
+int qcrypto_cryptodev_backend_sym_close_session(
+           QCryptoCryptoDevBackend *backend,
+           uint64_t session_id, Error **errp);
+
+/**
+ * qcrypto_cryptodev_backend_sym_operation:
+ * @backend: the cryptodev backend object
+ * @op_info: parameters needed by symmetric crypto operation
+ * @queue_index: queue index of cryptodev backend client
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Do symmetric crypto operation, such as encryption and
+ * decryption
+ *
+ * Returns: 0 on success, or Negative on error
+ */
+int qcrypto_cryptodev_backend_sym_operation(
+                 QCryptoCryptoDevBackend *backend,
+                 QCryptoCryptoDevBackendSymOpInfo *op_info,
+                 uint32_t queue_index, Error **errp);
+
 #endif /* QCRYPTO_CRYPTODEV_H */
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 03/10] virtio-crypto: introduce virtio_crypto.h
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 01/10] cryptodev: introduce cryptodev backend interface Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 02/10] cryptodev: add symmetric algorithm operation stuff Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend Gonglei
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

Introdue the virtio_crypto.h which follows
virtio-crypto specification.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 include/standard-headers/linux/virtio_crypto.h | 466 +++++++++++++++++++++++++
 1 file changed, 466 insertions(+)
 create mode 100644 include/standard-headers/linux/virtio_crypto.h

diff --git a/include/standard-headers/linux/virtio_crypto.h b/include/standard-headers/linux/virtio_crypto.h
new file mode 100644
index 0000000..9648984
--- /dev/null
+++ b/include/standard-headers/linux/virtio_crypto.h
@@ -0,0 +1,466 @@
+#ifndef _VIRTIO_CRYPTO_H
+#define _VIRTIO_CRYPTO_H
+
+#include "standard-headers/linux/types.h"
+#include "standard-headers/linux/virtio_config.h"
+#include "standard-headers/linux/virtio_types.h"
+
+
+struct virtio_crypto_iovec {
+    /* Guest physical address */
+    __virtio64 addr;
+    /* Length of guest physical address */
+    __virtio32 len;
+
+/* This marks a buffer as continuing via the next field */
+#define VIRTIO_CRYPTO_IOVEC_F_NEXT 1
+    /* The flags as indicated above. */
+    __virtio32 flags;
+    /* Pointer to next struct virtio_crypto_iovec if flags & NEXT */
+    __virtio64 next_iovec;
+};
+
+
+#define VIRTIO_CRYPTO_SERVICE_CIPHER (0)
+#define VIRTIO_CRYPTO_SERVICE_HASH (1)
+#define VIRTIO_CRYPTO_SERVICE_MAC  (2)
+#define VIRTIO_CRYPTO_SERVICE_AEAD (3)
+
+#define VIRTIO_CRYPTO_OPCODE(service, op)   ((service << 8) | (op))
+
+struct virtio_crypto_ctrl_header {
+#define VIRTIO_CRYPTO_CIPHER_CREATE_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_CIPHER, 0x02)
+#define VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_CIPHER, 0x03)
+#define VIRTIO_CRYPTO_HASH_CREATE_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_HASH, 0x02)
+#define VIRTIO_CRYPTO_HASH_DESTROY_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_HASH, 0x03)
+#define VIRTIO_CRYPTO_MAC_CREATE_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_MAC, 0x02)
+#define VIRTIO_CRYPTO_MAC_DESTROY_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_MAC, 0x03)
+#define VIRTIO_CRYPTO_AEAD_CREATE_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x02)
+#define VIRTIO_CRYPTO_AEAD_DESTROY_SESSION \
+       VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x03)
+    __virtio32 opcode;
+    __virtio32 algo;
+    __virtio32 flag;
+    /* data virtqueue id */
+    __virtio32 queue_id;
+};
+
+struct virtio_crypto_cipher_session_para {
+#define VIRTIO_CRYPTO_NO_CIPHER                 0
+#define VIRTIO_CRYPTO_CIPHER_ARC4               1
+#define VIRTIO_CRYPTO_CIPHER_AES_ECB            2
+#define VIRTIO_CRYPTO_CIPHER_AES_CBC            3
+#define VIRTIO_CRYPTO_CIPHER_AES_CTR            4
+#define VIRTIO_CRYPTO_CIPHER_DES_ECB            5
+#define VIRTIO_CRYPTO_CIPHER_DES_CBC            6
+#define VIRTIO_CRYPTO_CIPHER_3DES_ECB           7
+#define VIRTIO_CRYPTO_CIPHER_3DES_CBC           8
+#define VIRTIO_CRYPTO_CIPHER_3DES_CTR           9
+#define VIRTIO_CRYPTO_CIPHER_KASUMI_F8          10
+#define VIRTIO_CRYPTO_CIPHER_SNOW3G_UEA2        11
+#define VIRTIO_CRYPTO_CIPHER_AES_F8             12
+#define VIRTIO_CRYPTO_CIPHER_AES_XTS            13
+#define VIRTIO_CRYPTO_CIPHER_ZUC_EEA3           14
+    __virtio32 algo;
+    /* length of key */
+    __virtio32 keylen;
+
+#define VIRTIO_CRYPTO_OP_ENCRYPT  1
+#define VIRTIO_CRYPTO_OP_DECRYPT  2
+    /* encrypt or decrypt */
+    __virtio32 op;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_session_input {
+    /* Device-writable part */
+    __virtio64 session_id;
+    __virtio32 status;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_cipher_session_output {
+    __virtio64 key_addr; /* guest key physical address */
+};
+
+struct virtio_crypto_cipher_session_req {
+    struct virtio_crypto_cipher_session_para para;
+    struct virtio_crypto_cipher_session_output out;
+    struct virtio_crypto_session_input input;
+};
+
+struct virtio_crypto_hash_session_para {
+#define VIRTIO_CRYPTO_NO_HASH            0
+#define VIRTIO_CRYPTO_HASH_MD5           1
+#define VIRTIO_CRYPTO_HASH_SHA1          2
+#define VIRTIO_CRYPTO_HASH_SHA_224       3
+#define VIRTIO_CRYPTO_HASH_SHA_256       4
+#define VIRTIO_CRYPTO_HASH_SHA_384       5
+#define VIRTIO_CRYPTO_HASH_SHA_512       6
+#define VIRTIO_CRYPTO_HASH_SHA3_224      7
+#define VIRTIO_CRYPTO_HASH_SHA3_256      8
+#define VIRTIO_CRYPTO_HASH_SHA3_384      9
+#define VIRTIO_CRYPTO_HASH_SHA3_512      10
+#define VIRTIO_CRYPTO_HASH_SHA3_SHAKE128      11
+#define VIRTIO_CRYPTO_HASH_SHA3_SHAKE256      12
+    __virtio32 algo;
+    /* hash result length */
+    __virtio32 hash_result_len;
+};
+
+struct virtio_crypto_hash_create_session_req {
+    struct virtio_crypto_hash_session_para para;
+    struct virtio_crypto_session_input input;
+};
+
+struct virtio_crypto_mac_session_para {
+#define VIRTIO_CRYPTO_NO_MAC                       0
+#define VIRTIO_CRYPTO_MAC_HMAC_MD5                 1
+#define VIRTIO_CRYPTO_MAC_HMAC_SHA1                2
+#define VIRTIO_CRYPTO_MAC_HMAC_SHA_224             3
+#define VIRTIO_CRYPTO_MAC_HMAC_SHA_256             4
+#define VIRTIO_CRYPTO_MAC_HMAC_SHA_384             5
+#define VIRTIO_CRYPTO_MAC_HMAC_SHA_512             6
+#define VIRTIO_CRYPTO_MAC_CMAC_3DES                25
+#define VIRTIO_CRYPTO_MAC_CMAC_AES                 26
+#define VIRTIO_CRYPTO_MAC_KASUMI_F9                27
+#define VIRTIO_CRYPTO_MAC_SNOW3G_UIA2              28
+#define VIRTIO_CRYPTO_MAC_GMAC_AES                 41
+#define VIRTIO_CRYPTO_MAC_GMAC_TWOFISH             42
+#define VIRTIO_CRYPTO_MAC_CBCMAC_AES               49
+#define VIRTIO_CRYPTO_MAC_CBCMAC_KASUMI_F9         50
+#define VIRTIO_CRYPTO_MAC_XCBC_AES                 53
+    __virtio32 algo;
+    /* hash result length */
+    __virtio32 hash_result_len;
+    /* length of authenticated key */
+    __virtio32 auth_key_len;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_mac_session_output {
+    __virtio64 auth_key_addr; /* guest key physical address */
+};
+
+struct virtio_crypto_mac_create_session_req {
+    struct virtio_crypto_mac_session_para para;
+    struct virtio_crypto_mac_session_output out;
+    struct virtio_crypto_session_input input;
+};
+
+struct virtio_crypto_aead_session_para {
+#define VIRTIO_CRYPTO_NO_AEAD     0
+#define VIRTIO_CRYPTO_AEAD_GCM    1
+#define VIRTIO_CRYPTO_AEAD_CCM    2
+#define VIRTIO_CRYPTO_AEAD_CHACHA20_POLY1305  3
+    __virtio32 algo;
+    /* length of key */
+    __virtio32 key_len;
+    /* digest result length */
+    __virtio32 digest_result_len;
+    /* length of the additional authenticated data (AAD) in bytes */
+    __virtio32 aad_len;
+    /* encrypt or decrypt, See above VIRTIO_CRYPTO_OP_* */
+    __virtio32 op;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_aead_session_output {
+    __virtio64 key_addr; /* guest key physical address */
+};
+
+struct virtio_crypto_aead_create_session_req {
+    struct virtio_crypto_aead_session_para para;
+    struct virtio_crypto_aead_session_output out;
+    struct virtio_crypto_session_input input;
+};
+
+struct virtio_crypto_alg_chain_session_para {
+#define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_HASH_THEN_CIPHER  1
+#define VIRTIO_CRYPTO_SYM_ALG_CHAIN_ORDER_CIPHER_THEN_HASH  2
+    __virtio32 alg_chain_order;
+/* Plain hash */
+#define VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN    1
+/* Authenticated hash (mac) */
+#define VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH     2
+/* Nested hash */
+#define VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED   3
+    __virtio32 hash_mode;
+    struct virtio_crypto_cipher_session_para cipher_param;
+    union {
+        struct virtio_crypto_hash_session_para hash_param;
+        struct virtio_crypto_mac_session_para mac_param;
+    } u;
+    /* length of the additional authenticated data (AAD) in bytes */
+    __virtio32 aad_len;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_alg_chain_session_output {
+    struct virtio_crypto_cipher_session_output cipher;
+    struct virtio_crypto_mac_session_output mac;
+};
+
+struct virtio_crypto_alg_chain_session_req {
+    struct virtio_crypto_alg_chain_session_para para;
+    struct virtio_crypto_alg_chain_session_output out;
+    struct virtio_crypto_session_input input;
+};
+
+struct virtio_crypto_sym_create_session_req {
+    union {
+        struct virtio_crypto_cipher_session_req cipher;
+        struct virtio_crypto_alg_chain_session_req chain;
+    } u;
+
+    /* Device-readable part */
+
+/* No operation */
+#define VIRTIO_CRYPTO_SYM_OP_NONE  0
+/* Cipher only operation on the data */
+#define VIRTIO_CRYPTO_SYM_OP_CIPHER  1
+/* Chain any cipher with any hash or mac operation. The order
+   depends on the value of alg_chain_order param */
+#define VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING  2
+    __virtio32 op_type;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_destroy_session_req {
+    /* Device-readable part */
+    __virtio64  session_id;
+    /* Device-writable part */
+    __virtio32  status;
+    __virtio32  padding;
+};
+
+/* The request of the control viritqueue's packet */
+struct virtio_crypto_op_ctrl_req {
+    struct virtio_crypto_ctrl_header header;
+
+    union {
+        struct virtio_crypto_sym_create_session_req   sym_create_session;
+        struct virtio_crypto_hash_create_session_req  hash_create_session;
+        struct virtio_crypto_mac_create_session_req   mac_create_session;
+        struct virtio_crypto_aead_create_session_req  aead_create_session;
+        struct virtio_crypto_destroy_session_req      destroy_session;
+    } u;
+};
+
+struct virtio_crypto_op_header {
+#define VIRTIO_CRYPTO_CIPHER_ENCRYPT \
+    VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_CIPHER, 0x00)
+#define VIRTIO_CRYPTO_CIPHER_DECRYPT \
+    VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_CIPHER, 0x01)
+#define VIRTIO_CRYPTO_HASH \
+    VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_HASH, 0x00)
+#define VIRTIO_CRYPTO_MAC \
+    VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_MAC, 0x00)
+#define VIRTIO_CRYPTO_AEAD_ENCRYPT \
+    VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x00)
+#define VIRTIO_CRYPTO_AEAD_DECRYPT \
+    VIRTIO_CRYPTO_OPCODE(VIRTIO_CRYPTO_SERVICE_AEAD, 0x01)
+    __virtio32 opcode;
+    /* algo should be service-specific algorithms */
+    __virtio32 algo;
+    /* session_id should be service-specific algorithms */
+    __virtio64 session_id;
+    /* control flag to control the request */
+    __virtio32 flag;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_sym_input {
+    /* destination data, it's useless for plain HASH and MAC */
+    struct virtio_crypto_iovec dst_data;
+    /* digest result guest address, it's useless for plain cipher algos */
+    __virtio64 digest_result_addr;
+    /* digest result length which is the same with session para above */
+    __virtio32 digest_result_len;
+
+    __virtio32 status;
+};
+
+struct virtio_crypto_cipher_para {
+    __virtio32 iv_len;
+    /* length of source data */
+    __virtio32 src_data_len;
+    /* length of dst data */
+    __virtio32 dst_data_len;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_cipher_input {
+    struct virtio_crypto_sym_input input;
+};
+
+struct virtio_crypto_cipher_output {
+    /* iv guest address */
+    __virtio64 iv_addr;
+    /* source data */
+    struct virtio_crypto_iovec src_data;
+};
+
+struct virtio_crypto_hash_input {
+    struct virtio_crypto_sym_input input;
+};
+
+struct virtio_crypto_hash_output {
+    /* source data */
+    struct virtio_crypto_iovec src_data;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_mac_input {
+    struct virtio_crypto_sym_input input;
+};
+
+struct virtio_crypto_mac_output {
+    struct virtio_crypto_hash_output hash_output;
+};
+
+struct virtio_crypto_aead_para {
+    __virtio32 iv_len;
+    /* length of additional auth data */
+    __virtio32 aad_len;
+    /* length of source data */
+    __virtio32 src_data_len;
+    /* length of dst data */
+    __virtio32 dst_data_len;
+};
+
+struct virtio_crypto_aead_input {
+    struct virtio_crypto_sym_input input;
+};
+
+struct virtio_crypto_aead_output {
+    __virtio64 iv_addr; /* iv guest address */
+    /* source data */
+    struct virtio_crypto_iovec src_data;
+    /* additional auth data guest address */
+    struct virtio_crypto_iovec add_data;
+};
+
+struct virtio_crypto_cipher_data_req {
+    /* Device-readable part */
+    struct virtio_crypto_cipher_para para;
+    struct virtio_crypto_cipher_output odata;
+    /* Device-writable part */
+    struct virtio_crypto_cipher_input idata;
+};
+
+struct virtio_crypto_hash_data_req {
+    /* Device-readable part */
+    struct virtio_crypto_hash_output odata;
+    /* Device-writable part */
+    struct virtio_crypto_hash_input idata;
+};
+
+struct virtio_crypto_mac_data_req {
+    /* Device-readable part */
+    struct virtio_crypto_mac_output odata;
+    /* Device-writable part */
+    struct virtio_crypto_mac_input idata;
+};
+
+struct virtio_crypto_alg_chain_data_para {
+    struct virtio_crypto_cipher_para cipher;
+};
+
+struct virtio_crypto_alg_chain_data_output {
+    /* Device-writable part */
+    struct virtio_crypto_cipher_output cipher;
+
+    /* Device-readable part */
+    /* additional auth data guest address */
+    struct virtio_crypto_iovec add_data;
+};
+
+struct virtio_crypto_alg_chain_data_input {
+    struct virtio_crypto_sym_input input;
+};
+
+struct virtio_crypto_alg_chain_data_req {
+    /* Device-readable part */
+    struct virtio_crypto_alg_chain_data_para para;
+    struct virtio_crypto_alg_chain_data_output odata;
+    /* Device-writable part */
+    struct virtio_crypto_alg_chain_data_input idata;
+};
+
+struct virtio_crypto_sym_data_req {
+    union {
+        struct virtio_crypto_cipher_data_req cipher;
+        struct virtio_crypto_alg_chain_data_req chain;
+    } u;
+
+    /* Device-readable part */
+
+    /* See above VIRTIO_CRYPTO_SYM_OP_* */
+    __virtio32 op_type;
+    __virtio32 padding;
+};
+
+struct virtio_crypto_aead_data_req {
+    /* Device-readable part */
+    struct virtio_crypto_aead_para para;
+    struct virtio_crypto_aead_output odata;
+    /* Device-writable part */
+    struct virtio_crypto_aead_input idata;
+};
+
+/* The request of the data viritqueue's packet */
+struct virtio_crypto_op_data_req {
+    struct virtio_crypto_op_header header;
+
+    union {
+        struct virtio_crypto_sym_data_req  sym_req;
+        struct virtio_crypto_hash_data_req hash_req;
+        struct virtio_crypto_mac_data_req mac_req;
+        struct virtio_crypto_aead_data_req aead_req;
+    } u;
+};
+
+#define VIRTIO_CRYPTO_OP_OK        0
+#define VIRTIO_CRYPTO_OP_ERR       1
+#define VIRTIO_CRYPTO_OP_BADMSG    2
+#define VIRTIO_CRYPTO_OP_NOTSUPP   3
+#define VIRTIO_CRYPTO_OP_INVSESS   4 /* Invaild session id */
+
+/* The accelerator hardware is ready */
+#define VIRTIO_CRYPTO_S_HW_READY  (1 << 0)
+#define VIRTIO_CRYPTO_S_STARTED  (1 << 1)
+
+struct virtio_crypto_config {
+    /* See VIRTIO_CRYPTO_OP_* above */
+    __virtio32  status;
+
+    /*
+     * Maximum number of data queue legal values are between 1 and 0x8000
+     */
+    __virtio32  max_dataqueues;
+
+    /* Specifies the services mask which the devcie support,
+       see VIRTIO_CRYPTO_SERVICE_* above */
+    __virtio32 crypto_services;
+
+    /* Detailed algorithms mask */
+    __virtio32 cipher_algo_l;
+    __virtio32 cipher_algo_h;
+    __virtio32 hash_algo;
+    __virtio32 mac_algo_l;
+    __virtio32 mac_algo_h;
+    __virtio32 asym_algo;
+    __virtio32 kdf_algo;
+    __virtio32 aead_algo;
+    __virtio32 primitive_algo;
+};
+
+#endif
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (2 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 03/10] virtio-crypto: introduce virtio_crypto.h Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:29   ` Daniel P. Berrange
  2016-09-19  8:56   ` Daniel P. Berrange
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 05/10] virtio-crypto: add virtio crypto device emulation Gonglei
                   ` (7 subsequent siblings)
  11 siblings, 2 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 crypto/Makefile.objs      |   1 +
 crypto/cryptodev-gcrypt.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++
 qemu-options.hx           |  18 +++
 3 files changed, 348 insertions(+)
 create mode 100644 crypto/cryptodev-gcrypt.c

diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index f7f3c4f..bd8aea7 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -27,6 +27,7 @@ crypto-obj-y += block.o
 crypto-obj-y += block-qcow.o
 crypto-obj-y += block-luks.o
 crypto-obj-y += cryptodev.o
+crypto-obj-$(CONFIG_GCRYPT) += cryptodev-gcrypt.o
 
 # Let the userspace emulators avoid linking gnutls/etc
 crypto-aes-obj-y = aes.o
diff --git a/crypto/cryptodev-gcrypt.c b/crypto/cryptodev-gcrypt.c
new file mode 100644
index 0000000..66a0e5e
--- /dev/null
+++ b/crypto/cryptodev-gcrypt.c
@@ -0,0 +1,329 @@
+/*
+ * QEMU Cryptodev backend for gcrypt
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ *
+ * Authors:
+ *    Gonglei <arei.gonglei@huawei.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "crypto/cryptodev.h"
+#include "hw/boards.h"
+#include "qapi/error.h"
+#include "standard-headers/linux/virtio_crypto.h"
+#include "crypto/cipher.h"
+
+
+/**
+ * @TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT:
+ * name of backend that uses gcrypt library
+ */
+#define TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT "cryptodev-backend-gcrypt"
+
+#define QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(obj) \
+    OBJECT_CHECK(QCryptoCryptoDevBackendGcrypt, \
+                 (obj), TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT)
+
+typedef struct QCryptoCryptoDevBackendGcrypt
+                         QCryptoCryptoDevBackendGcrypt;
+
+typedef struct QCryptoCryptoDevBackendGcryptSession {
+    QCryptoCipher *cipher;
+    uint8_t direction; /* encryption or decryption */
+    uint8_t type; /* cipher? hash? aead? */
+    QTAILQ_ENTRY(QCryptoCryptoDevBackendGcryptSession) next;
+} QCryptoCryptoDevBackendGcryptSession;
+
+/* Max number of symetrical sessions */
+#define MAX_NUM_SESSIONS 256
+
+
+struct QCryptoCryptoDevBackendGcrypt {
+    QCryptoCryptoDevBackend parent_obj;
+
+    QCryptoCryptoDevBackendGcryptSession *sessions[MAX_NUM_SESSIONS];
+};
+
+static void qcrypto_cryptodev_backend_gcrypt_init(
+             QCryptoCryptoDevBackend *backend, Error **errp)
+{
+    /* Only support one queue */
+    int queues = MAX(backend->conf.peers.queues, 1);
+    int i;
+    QCryptoCryptoDevBackendClientState *cc;
+
+    for (i = 0; i < queues; i++) {
+        cc = qcrypto_cryptodev_backend_new_client(
+                  "cryptodev-gcrypt", NULL);
+        snprintf(cc->info_str, sizeof(cc->info_str),
+                 "cryptodev-gcrypt%d", i);
+        cc->queue_index = i;
+
+        backend->conf.peers.ccs[i] = cc;
+    }
+
+    backend->conf.crypto_services =
+                         1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
+                         1u << VIRTIO_CRYPTO_SERVICE_HASH |
+                         1u << VIRTIO_CRYPTO_SERVICE_MAC;
+    backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
+    backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
+}
+
+static int
+qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(
+      QCryptoCryptoDevBackendGcrypt *gcrypt)
+{
+    int i;
+
+    for (i = 0; i < MAX_NUM_SESSIONS; i++) {
+        if (gcrypt->sessions[i] == NULL) {
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+static int qcrypto_cryptodev_backend_gcrypt_create_cipher_session(
+                    QCryptoCryptoDevBackendGcrypt *gcrypt,
+                    QCryptoCryptoDevBackendSymSessionInfo *sess_info,
+                    Error **errp)
+{
+    int algo;
+    int mode;
+    QCryptoCipher *cipher;
+    int index;
+    QCryptoCryptoDevBackendGcryptSession *sess;
+
+    if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) {
+        error_setg(errp, "unsupported optype :%u", sess_info->op_type);
+        return -1;
+    }
+
+    index = qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(gcrypt);
+    if (index < 0) {
+        error_setg(errp, "the total number of created session exceed %u",
+                  MAX_NUM_SESSIONS);
+        return -1;
+    }
+
+    switch (sess_info->cipher_alg) {
+    case VIRTIO_CRYPTO_CIPHER_AES_ECB:
+        if (sess_info->key_len == 128 / 8) {
+            algo = QCRYPTO_CIPHER_ALG_AES_128;
+        } else if (sess_info->key_len == 192 / 8) {
+            algo = QCRYPTO_CIPHER_ALG_AES_192;
+        } else if (sess_info->key_len == 256 / 8) {
+            algo = QCRYPTO_CIPHER_ALG_AES_256;
+        } else {
+            error_setg(errp, "unsupported key length :%u",
+                       sess_info->key_len);
+            return -1;
+        }
+        mode = QCRYPTO_CIPHER_MODE_ECB;
+        break;
+    case VIRTIO_CRYPTO_CIPHER_AES_CBC:
+        if (sess_info->key_len == 128 / 8) {
+            algo = QCRYPTO_CIPHER_ALG_AES_128;
+        } else if (sess_info->key_len == 192 / 8) {
+            algo = QCRYPTO_CIPHER_ALG_AES_192;
+        } else if (sess_info->key_len == 256 / 8) {
+            algo = QCRYPTO_CIPHER_ALG_AES_256;
+        } else {
+            error_setg(errp, "unsupported key length :%u",
+                       sess_info->key_len);
+            return -1;
+        }
+        mode = QCRYPTO_CIPHER_MODE_CBC;
+        break;
+    case VIRTIO_CRYPTO_CIPHER_AES_CTR:
+    default:
+        error_setg(errp, "unsupported cipher alg :%u",
+                   sess_info->cipher_alg);
+        return -1;
+    }
+
+    cipher = qcrypto_cipher_new(algo, mode,
+                               sess_info->cipher_key,
+                               sess_info->key_len,
+                               errp);
+    if (!cipher) {
+        return -1;
+    }
+
+    sess = g_new0(QCryptoCryptoDevBackendGcryptSession, 1);
+    sess->cipher = cipher;
+    sess->direction = sess_info->direction;
+    sess->type = sess_info->op_type;
+
+    gcrypt->sessions[index] = sess;
+
+    return index;
+}
+
+static int64_t qcrypto_cryptodev_backend_gcrypt_sym_create_session(
+           QCryptoCryptoDevBackend *backend,
+           QCryptoCryptoDevBackendSymSessionInfo *sess_info,
+           uint32_t queue_index, Error **errp)
+{
+    QCryptoCryptoDevBackendGcrypt *gcrypt =
+                      QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend);
+    int64_t session_id = -1;
+    int ret;
+
+    switch (sess_info->op_code) {
+    case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
+        ret = qcrypto_cryptodev_backend_gcrypt_create_cipher_session(
+                           gcrypt, sess_info, errp);
+        if (ret < 0) {
+            return ret;
+        } else {
+            session_id = ret;
+        }
+        break;
+    case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
+    case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
+    default:
+        error_setg(errp, "unsupported opcode :%" PRIu32 "",
+                   sess_info->op_code);
+        return -1;
+    }
+
+    return session_id;
+}
+
+static int qcrypto_cryptodev_backend_gcrypt_sym_close_session(
+           QCryptoCryptoDevBackend *backend,
+           uint64_t session_id, Error **errp)
+{
+    QCryptoCryptoDevBackendGcrypt *gcrypt =
+                      QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend);
+
+    if (session_id >= MAX_NUM_SESSIONS ||
+              gcrypt->sessions[session_id] == NULL) {
+        error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
+                      session_id);
+        return -1;
+    }
+
+    qcrypto_cipher_free(gcrypt->sessions[session_id]->cipher);
+    g_free(gcrypt->sessions[session_id]);
+    gcrypt->sessions[session_id] = NULL;
+    return 0;
+}
+
+static int qcrypto_cryptodev_backend_gcrypt_sym_operation(
+                 QCryptoCryptoDevBackend *backend,
+                 QCryptoCryptoDevBackendSymOpInfo *op_info,
+                 uint32_t queue_index, Error **errp)
+{
+    QCryptoCryptoDevBackendGcrypt *gcrypt =
+                      QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend);
+    QCryptoCryptoDevBackendGcryptSession *sess;
+    int ret;
+
+    if (op_info->session_id >= MAX_NUM_SESSIONS ||
+              gcrypt->sessions[op_info->session_id] == NULL) {
+        error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
+                   op_info->session_id);
+        return -VIRTIO_CRYPTO_OP_INVSESS;
+    }
+
+    sess = gcrypt->sessions[op_info->session_id];
+
+    ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv,
+                               op_info->iv_len, errp);
+    if (ret < 0) {
+        return -VIRTIO_CRYPTO_OP_ERR;
+    }
+
+    if (sess->direction == VIRTIO_CRYPTO_OP_ENCRYPT) {
+        ret = qcrypto_cipher_encrypt(sess->cipher, op_info->src,
+                                     op_info->dst, op_info->src_len, errp);
+        if (ret < 0) {
+            return -VIRTIO_CRYPTO_OP_ERR;
+        }
+    } else {
+        ret = qcrypto_cipher_decrypt(sess->cipher, op_info->src,
+                                     op_info->dst, op_info->src_len, errp);
+        if (ret < 0) {
+            return -VIRTIO_CRYPTO_OP_ERR;
+        }
+    }
+    return 0;
+}
+
+static void qcrypto_cryptodev_backend_gcrypt_cleanup(
+             QCryptoCryptoDevBackend *backend,
+             Error **errp)
+{
+    QCryptoCryptoDevBackendGcrypt *gcrypt =
+                      QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend);
+    int i;
+    int queues = backend->conf.peers.queues;
+    QCryptoCryptoDevBackendClientState *cc;
+
+    for (i = 0; i < MAX_NUM_SESSIONS; i++) {
+        if (gcrypt->sessions[i] != NULL) {
+            qcrypto_cryptodev_backend_gcrypt_sym_close_session(
+                    backend, i, errp);
+        }
+    }
+
+    for (i = 0; i < queues; i++) {
+        cc = backend->conf.peers.ccs[i];
+        if (cc) {
+            qcrypto_cryptodev_backend_free_client(cc);
+            backend->conf.peers.ccs[i] = NULL;
+        }
+    }
+}
+
+static void qcrypto_cryptodev_backend_gcrypt_finalize(Object *obj)
+{
+
+}
+
+static void
+qcrypto_cryptodev_backend_gcrypt_class_init(ObjectClass *oc, void *data)
+{
+    QCryptoCryptoDevBackendClass *bc = QCRYPTO_CRYPTODEV_BACKEND_CLASS(oc);
+
+    bc->init = qcrypto_cryptodev_backend_gcrypt_init;
+    bc->cleanup = qcrypto_cryptodev_backend_gcrypt_cleanup;
+    bc->create_session = qcrypto_cryptodev_backend_gcrypt_sym_create_session;
+    bc->close_session = qcrypto_cryptodev_backend_gcrypt_sym_close_session;
+    bc->do_sym_op = qcrypto_cryptodev_backend_gcrypt_sym_operation;
+}
+
+static const TypeInfo qcrypto_cryptodev_backend_gcrypt_info = {
+    .name = TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT,
+    .parent = TYPE_QCRYPTO_CRYPTODEV_BACKEND,
+    .class_init = qcrypto_cryptodev_backend_gcrypt_class_init,
+    .instance_finalize = qcrypto_cryptodev_backend_gcrypt_finalize,
+    .instance_size = sizeof(QCryptoCryptoDevBackendGcrypt),
+};
+
+static void
+qcrypto_cryptodev_backend_gcrypt_register_types(void)
+{
+    type_register_static(&qcrypto_cryptodev_backend_gcrypt_info);
+}
+
+type_init(qcrypto_cryptodev_backend_gcrypt_register_types);
diff --git a/qemu-options.hx b/qemu-options.hx
index a71aaf8..aff1217 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3887,6 +3887,24 @@ Dump the network traffic on netdev @var{dev} to the file specified by
 The file format is libpcap, so it can be analyzed with tools such as tcpdump
 or Wireshark.
 
+@item -object cryptodev-backend-gcrypt,id=@var{id}[,queues=@var{queues}]
+
+Creates a cryptodev backend which executes crypto opreation from
+the gcrypt library on the host. The @var{id} parameter is
+a unique ID that will be used to reference this cryptodev backend from
+the @option{virtio-crypto} device. The @var{queues} parameter is optional,
+which specify the queue number of cryptodev backend, the default of
+@var{queues} is 1.
+
+@example
+
+ # qemu-system-x86_64 \
+   [...] \
+       -object cryptodev-backend-gcrypt,id=cryptodev0 \
+       -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \
+   [...]
+@end example
+
 @item -object secret,id=@var{id},data=@var{string},format=@var{raw|base64}[,keyid=@var{secretid},iv=@var{string}]
 @item -object secret,id=@var{id},file=@var{filename},format=@var{raw|base64}[,keyid=@var{secretid},iv=@var{string}]
 
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 05/10] virtio-crypto: add virtio crypto device emulation
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (3 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 06/10] virtio-crypto-pci: add virtio crypto pci support Gonglei
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

Introduce the virtio crypto realization, I'll
finish the core code in the following patches. The
thoughts came from virtio net realization.

For more information see:
http://qemu-project.org/Features/VirtioCrypto

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 hw/virtio/Makefile.objs           |   1 +
 hw/virtio/virtio-crypto.c         | 197 ++++++++++++++++++++++++++++++++++++++
 include/hw/virtio/virtio-crypto.h |  75 +++++++++++++++
 3 files changed, 273 insertions(+)
 create mode 100644 hw/virtio/virtio-crypto.c
 create mode 100644 include/hw/virtio/virtio-crypto.h

diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index e716308..968f392 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -7,3 +7,4 @@ obj-y += virtio.o virtio-balloon.o
 obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
 
 obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o
+obj-y += virtio-crypto.o
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
new file mode 100644
index 0000000..b1c10b2
--- /dev/null
+++ b/hw/virtio/virtio-crypto.c
@@ -0,0 +1,197 @@
+/*
+ * Virtio crypto Support
+ *
+ * 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
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "qemu/iov.h"
+#include "hw/qdev.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-crypto.h"
+#include "hw/virtio/virtio-access.h"
+
+static void virtio_crypto_process(VirtIOCrypto *vcrypto)
+{
+}
+
+static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+
+}
+
+static void virtio_crypto_handle_dataq(VirtIODevice *vdev, VirtQueue *vq)
+{
+
+}
+
+static uint64_t virtio_crypto_get_features(VirtIODevice *vdev,
+                                           uint64_t features,
+                                           Error **errp)
+{
+    return features;
+}
+
+static void virtio_crypto_set_features(VirtIODevice *vdev, uint64_t features)
+{
+
+}
+
+static void virtio_crypto_save(QEMUFile *f, void *opaque)
+{
+    VirtIODevice *vdev = opaque;
+
+    virtio_save(vdev, f);
+}
+
+static int virtio_crypto_load(QEMUFile *f, void *opaque, int version_id)
+{
+    VirtIOCrypto *vcrypto = opaque;
+    int ret;
+
+    if (version_id != 1) {
+        return -EINVAL;
+    }
+    ret = virtio_load(VIRTIO_DEVICE(vcrypto), f, version_id);
+    if (ret != 0) {
+        return ret;
+    }
+
+    /* We may have an element ready but couldn't process it due to a quota
+     * limit.  Make sure to try again after live migration when the quota may
+     * have been reset.
+     */
+    virtio_crypto_process(vcrypto);
+
+    return 0;
+}
+
+static void virtio_crypto_reset(VirtIODevice *vdev)
+{
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
+    /* multiqueue is disabled by default */
+    vcrypto->curr_queues = 1;
+    if (!vcrypto->cryptodev->ready) {
+        vcrypto->status &= ~VIRTIO_CRYPTO_S_HW_READY;
+    } else {
+        vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY;
+    }
+}
+
+static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
+    int i;
+
+    vcrypto->cryptodev = vcrypto->conf.cryptodev;
+    if (vcrypto->cryptodev == NULL) {
+        error_setg(errp, "'cryptodev' parameter expects a valid object");
+        return;
+    }
+
+    vcrypto->max_queues = MAX(vcrypto->cryptodev->conf.peers.queues, 1);
+    if (vcrypto->max_queues + 1 > VIRTIO_QUEUE_MAX) {
+        error_setg(errp, "Invalid number of queues (= %" PRIu16 "), "
+                   "must be a postive integer less than %d.",
+                   vcrypto->max_queues, VIRTIO_QUEUE_MAX - 1);
+        return;
+    }
+
+    virtio_init(vdev, "virtio-crypto", VIRTIO_ID_CRYPTO, vcrypto->config_size);
+    vcrypto->curr_queues = 1;
+
+    for (i = 0; i < vcrypto->max_queues; i++) {
+        virtio_add_queue(vdev, 1024, virtio_crypto_handle_dataq);
+    }
+
+    vcrypto->ctrl_vq = virtio_add_queue(vdev, 64, virtio_crypto_handle_ctrl);
+    if (!vcrypto->cryptodev->ready) {
+        vcrypto->status &= ~VIRTIO_CRYPTO_S_HW_READY;
+    } else {
+        vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY;
+    }
+    register_savevm(dev, "virtio-crypto", -1, 1, virtio_crypto_save,
+                    virtio_crypto_load, vcrypto);
+}
+
+static void virtio_crypto_device_unrealize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(dev);
+
+    unregister_savevm(dev, "virtio-crypto", vcrypto);
+
+    virtio_cleanup(vdev);
+}
+
+static Property virtio_crypto_properties[] = {
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_crypto_get_config(VirtIODevice *vdev, uint8_t *config)
+{
+
+}
+
+static void virtio_crypto_set_config(VirtIODevice *vdev, const uint8_t *config)
+{
+
+}
+
+static void virtio_crypto_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+
+    dc->props = virtio_crypto_properties;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    vdc->realize = virtio_crypto_device_realize;
+    vdc->unrealize = virtio_crypto_device_unrealize;
+    vdc->get_config = virtio_crypto_get_config;
+    vdc->set_config = virtio_crypto_set_config;
+    vdc->get_features = virtio_crypto_get_features;
+    vdc->set_features = virtio_crypto_set_features;
+    vdc->reset = virtio_crypto_reset;
+}
+
+static void virtio_crypto_instance_init(Object *obj)
+{
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(obj);
+
+    /*
+     * The default config_size is sizeof(struct virtio_crypto_config).
+     * Can be overriden with virtio_crypto_set_config_size.
+     */
+    vcrypto->config_size = sizeof(struct virtio_crypto_config);
+
+    object_property_add_link(obj, "cryptodev",
+                             TYPE_QCRYPTO_CRYPTODEV_BACKEND,
+                             (Object **)&vcrypto->conf.cryptodev,
+                             qdev_prop_allow_set_link_before_realize,
+                             OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
+}
+
+static const TypeInfo virtio_crypto_info = {
+    .name = TYPE_VIRTIO_CRYPTO,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOCrypto),
+    .instance_init = virtio_crypto_instance_init,
+    .class_init = virtio_crypto_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_crypto_info);
+}
+
+type_init(virtio_register_types)
diff --git a/include/hw/virtio/virtio-crypto.h b/include/hw/virtio/virtio-crypto.h
new file mode 100644
index 0000000..2fe2499
--- /dev/null
+++ b/include/hw/virtio/virtio-crypto.h
@@ -0,0 +1,75 @@
+/*
+ * Virtio crypto Support
+ *
+ * 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
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ */
+
+#ifndef _QEMU_VIRTIO_CRYPTO_H
+#define _QEMU_VIRTIO_CRYPTO_H
+
+#include "standard-headers/linux/virtio_crypto.h"
+#include "hw/virtio/virtio.h"
+#include "sysemu/iothread.h"
+#include "crypto/cryptodev.h"
+
+#define VIRTIO_ID_CRYPTO 20
+
+/* #define DEBUG_VIRTIO_CRYPTO */
+
+#ifdef DEBUG_VIRTIO_CRYPTO
+#define DPRINTF(fmt, ...) \
+do { printf("virtio_crypto: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...) do { } while (0)
+#endif
+
+#define TYPE_VIRTIO_CRYPTO "virtio-crypto-device"
+#define VIRTIO_CRYPTO(obj) \
+        OBJECT_CHECK(VirtIOCrypto, (obj), TYPE_VIRTIO_CRYPTO)
+#define VIRTIO_CRYPTO_GET_PARENT_CLASS(obj) \
+        OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_CRYPTO)
+
+
+typedef struct VirtIOCryptoConf {
+    QCryptoCryptoDevBackend *cryptodev;
+} VirtIOCryptoConf;
+
+struct VirtIOCrypto;
+
+typedef struct VirtIOCryptoReq {
+    VirtQueueElement elem;
+    /* flags of operation, such as type of algorithm */
+    uint32_t flags;
+    /* address of in data (Device to Driver) */
+    void *idata_hva;
+    VirtQueue *vq;
+    struct VirtIOCrypto *vcrypto;
+    union {
+        QCryptoCryptoDevBackendSymOpInfo *sym_op_info;
+    } u;
+} VirtIOCryptoReq;
+
+typedef struct VirtIOCrypto {
+    VirtIODevice parent_obj;
+
+    VirtQueue *ctrl_vq;
+
+    VirtIOCryptoConf conf;
+    QCryptoCryptoDevBackend *cryptodev;
+
+    uint32_t max_queues;
+    uint32_t status;
+
+    int multiqueue;
+    uint32_t curr_queues;
+    size_t config_size;
+} VirtIOCrypto;
+
+#endif /* _QEMU_VIRTIO_CRYPTO_H */
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 06/10] virtio-crypto-pci: add virtio crypto pci support
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (4 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 05/10] virtio-crypto: add virtio crypto device emulation Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 07/10] virtio-crypto: set capacity of algorithms supported Gonglei
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

This patch adds virtio-crypto-pci, which is the pci proxy for the virtio
crypto device.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 hw/virtio/Makefile.objs       |  1 +
 hw/virtio/virtio-crypto-pci.c | 76 +++++++++++++++++++++++++++++++++++++++++++
 hw/virtio/virtio-pci.h        | 15 +++++++++
 3 files changed, 92 insertions(+)
 create mode 100644 hw/virtio/virtio-crypto-pci.c

diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index 968f392..95c4c30 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -8,3 +8,4 @@ obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
 
 obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o
 obj-y += virtio-crypto.o
+obj-$(CONFIG_VIRTIO_PCI) += virtio-crypto-pci.o
diff --git a/hw/virtio/virtio-crypto-pci.c b/hw/virtio/virtio-crypto-pci.c
new file mode 100644
index 0000000..011125a
--- /dev/null
+++ b/hw/virtio/virtio-crypto-pci.c
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * (at your option) any later version.  See the COPYING file in the
+ * top-level directory.
+ *
+ */
+#include "qemu/osdep.h"
+#include "hw/pci/pci.h"
+#include "hw/virtio/virtio.h"
+#include "hw/virtio/virtio-bus.h"
+#include "hw/virtio/virtio-pci.h"
+#include "hw/virtio/virtio-crypto.h"
+
+static Property virtio_crypto_pci_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_crypto_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
+{
+    VirtIOCryptoPCI *vcrypto = VIRTIO_CRYPTO_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&vcrypto->vdev);
+
+    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",
+                 NULL);
+}
+
+static void virtio_crypto_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+    k->realize = virtio_crypto_pci_realize;
+    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+    dc->props = virtio_crypto_pci_properties;
+
+    pcidev_k->class_id = PCI_CLASS_OTHERS;
+}
+
+static void virtio_crypto_initfn(Object *obj)
+{
+    VirtIOCryptoPCI *dev = VIRTIO_CRYPTO_PCI(obj);
+
+    virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
+                                TYPE_VIRTIO_CRYPTO);
+    object_property_add_alias(obj, "cryptodev", OBJECT(&dev->vdev),
+                              "cryptodev", &error_abort);
+}
+
+static const TypeInfo virtio_crypto_pci_info = {
+    .name          = TYPE_VIRTIO_CRYPTO_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOCryptoPCI),
+    .instance_init = virtio_crypto_initfn,
+    .class_init    = virtio_crypto_pci_class_init,
+};
+
+static void virtio_crypto_pci_register_types(void)
+{
+    type_register_static(&virtio_crypto_pci_info);
+}
+type_init(virtio_crypto_pci_register_types)
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 0698157..6a31fde 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -25,6 +25,8 @@
 #include "hw/virtio/virtio-bus.h"
 #include "hw/virtio/virtio-input.h"
 #include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-crypto.h"
+
 #ifdef CONFIG_VIRTFS
 #include "hw/9pfs/virtio-9p.h"
 #endif
@@ -48,6 +50,7 @@ typedef struct VirtIOInputHIDPCI VirtIOInputHIDPCI;
 typedef struct VirtIOInputHostPCI VirtIOInputHostPCI;
 typedef struct VirtIOGPUPCI VirtIOGPUPCI;
 typedef struct VHostVSockPCI VHostVSockPCI;
+typedef struct VirtIOCryptoPCI VirtIOCryptoPCI;
 
 /* virtio-pci-bus */
 
@@ -347,6 +350,18 @@ struct VHostVSockPCI {
 };
 #endif
 
+/*
+ * virtio-crypto-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_CRYPTO_PCI "virtio-crypto-pci"
+#define VIRTIO_CRYPTO_PCI(obj) \
+        OBJECT_CHECK(VirtIOCryptoPCI, (obj), TYPE_VIRTIO_CRYPTO_PCI)
+
+struct VirtIOCryptoPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOCrypto vdev;
+};
+
 /* Virtio ABI version, if we increment this, we break the guest driver. */
 #define VIRTIO_PCI_ABI_VERSION          0
 
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 07/10] virtio-crypto: set capacity of algorithms supported
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (5 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 06/10] virtio-crypto-pci: add virtio crypto pci support Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 08/10] virtio-crypto: add control queue handler Gonglei
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

Expose the capacity of algorithms supported by
virtio crypto device to the frontend driver using
pci configuration space.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 hw/virtio/virtio-crypto.c         | 39 ++++++++++++++++++++++++++++++++++++++-
 include/hw/virtio/virtio-crypto.h | 14 ++++++++++++++
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index b1c10b2..e78656c 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -87,6 +87,26 @@ static void virtio_crypto_reset(VirtIODevice *vdev)
     }
 }
 
+static void virtio_crypto_init_config(VirtIODevice *vdev)
+{
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
+
+    vcrypto->conf.crypto_services =
+                     vcrypto->conf.cryptodev->conf.crypto_services;
+    vcrypto->conf.cipher_algo_l =
+                     vcrypto->conf.cryptodev->conf.cipher_algo_l;
+    vcrypto->conf.cipher_algo_h =
+                     vcrypto->conf.cryptodev->conf.cipher_algo_h;
+    vcrypto->conf.hash_algo = vcrypto->conf.cryptodev->conf.hash_algo;
+    vcrypto->conf.mac_algo_l = vcrypto->conf.cryptodev->conf.mac_algo_l;
+    vcrypto->conf.mac_algo_h = vcrypto->conf.cryptodev->conf.mac_algo_h;
+    vcrypto->conf.asym_algo = vcrypto->conf.cryptodev->conf.asym_algo;
+    vcrypto->conf.kdf_algo = vcrypto->conf.cryptodev->conf.kdf_algo;
+    vcrypto->conf.aead_algo = vcrypto->conf.cryptodev->conf.aead_algo;
+    vcrypto->conf.primitive_algo =
+                     vcrypto->conf.cryptodev->conf.primitive_algo;
+}
+
 static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@@ -120,6 +140,7 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
     } else {
         vcrypto->status |= VIRTIO_CRYPTO_S_HW_READY;
     }
+    virtio_crypto_init_config(vdev);
     register_savevm(dev, "virtio-crypto", -1, 1, virtio_crypto_save,
                     virtio_crypto_load, vcrypto);
 }
@@ -140,7 +161,23 @@ static Property virtio_crypto_properties[] = {
 
 static void virtio_crypto_get_config(VirtIODevice *vdev, uint8_t *config)
 {
-
+    VirtIOCrypto *c = VIRTIO_CRYPTO(vdev);
+    struct virtio_crypto_config crypto_cfg;
+
+    crypto_cfg.status = c->status;
+    crypto_cfg.max_dataqueues = c->max_queues;
+    crypto_cfg.crypto_services = c->conf.crypto_services;
+    crypto_cfg.cipher_algo_l = c->conf.cipher_algo_l;
+    crypto_cfg.cipher_algo_h = c->conf.cipher_algo_h;
+    crypto_cfg.hash_algo = c->conf.hash_algo;
+    crypto_cfg.mac_algo_l = c->conf.mac_algo_l;
+    crypto_cfg.mac_algo_h = c->conf.mac_algo_h;
+    crypto_cfg.asym_algo = c->conf.asym_algo;
+    crypto_cfg.kdf_algo = c->conf.kdf_algo;
+    crypto_cfg.aead_algo = c->conf.aead_algo;
+    crypto_cfg.primitive_algo = c->conf.primitive_algo;
+
+    memcpy(config, &crypto_cfg, c->config_size);
 }
 
 static void virtio_crypto_set_config(VirtIODevice *vdev, const uint8_t *config)
diff --git a/include/hw/virtio/virtio-crypto.h b/include/hw/virtio/virtio-crypto.h
index 2fe2499..f6fe2d8 100644
--- a/include/hw/virtio/virtio-crypto.h
+++ b/include/hw/virtio/virtio-crypto.h
@@ -39,6 +39,20 @@ do { printf("virtio_crypto: " fmt , ## __VA_ARGS__); } while (0)
 
 typedef struct VirtIOCryptoConf {
     QCryptoCryptoDevBackend *cryptodev;
+
+    /* Supported service mask */
+    uint32_t crypto_services;
+
+    /* Detailed algorithms mask */
+    uint32_t cipher_algo_l;
+    uint32_t cipher_algo_h;
+    uint32_t hash_algo;
+    uint32_t mac_algo_l;
+    uint32_t mac_algo_h;
+    uint32_t asym_algo;
+    uint32_t kdf_algo;
+    uint32_t aead_algo;
+    uint32_t primitive_algo;
 } VirtIOCryptoConf;
 
 struct VirtIOCrypto;
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 08/10] virtio-crypto: add control queue handler
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (6 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 07/10] virtio-crypto: set capacity of algorithms supported Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 09/10] virtio-crypto: add data queue processing handler Gonglei
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

Realize the symmetric algorithm control queue handler,
including plain cipher and chainning algorithms.

Currently the control queue is used to create and
close session for symmetric algorithm.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 hw/virtio/virtio-crypto.c | 234 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 233 insertions(+), 1 deletion(-)

diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index e78656c..4318327 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -24,9 +24,241 @@ static void virtio_crypto_process(VirtIOCrypto *vcrypto)
 {
 }
 
-static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+static inline int virtio_crypto_vq2q(int queue_index)
+{
+    return queue_index;
+}
+
+static void
+virtio_crypto_cipher_session_helper(VirtIODevice *vdev,
+           QCryptoCryptoDevBackendSymSessionInfo *info,
+           struct virtio_crypto_cipher_session_para *cipher_para,
+           struct virtio_crypto_cipher_session_output *cipher_out)
+{
+    hwaddr key_gpa;
+    void *key_hva;
+    hwaddr len;
+
+    info->cipher_alg = cipher_para->algo;
+    info->key_len = cipher_para->keylen;
+    info->direction = cipher_para->op;
+    len = info->key_len;
+    /* get cipher key */
+    if (len > 0) {
+        DPRINTF("keylen=%" PRIu32 "\n", info->key_len);
+        key_gpa = cipher_out->key_addr;
+
+        key_hva = cpu_physical_memory_map(key_gpa, &len, 0);
+
+        info->cipher_key = g_malloc(info->key_len);
+        memcpy(info->cipher_key, key_hva, info->key_len);
+        cpu_physical_memory_unmap(key_hva, len, 0, len);
+    }
+}
+
+static int64_t
+virtio_crypto_create_sym_session(VirtIOCrypto *vcrypto,
+               struct virtio_crypto_sym_create_session_req *sess_req,
+               uint32_t queue_id,
+               uint32_t opcode,
+               VirtQueueElement *elem)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
+    QCryptoCryptoDevBackendSymSessionInfo info;
+    int64_t session_id;
+    int queue_index;
+    uint32_t op_type;
+    hwaddr auth_key_gpa;
+    void *auth_key_hva;
+    struct virtio_crypto_session_input *input;
+    hwaddr len;
+    size_t input_offset;
+    Error *local_err = NULL;
+    struct iovec *iov = elem->in_sg;
+
+    memset(&info, 0, sizeof(info));
+    op_type = sess_req->op_type;
+    info.op_type = op_type;
+    info.op_code = opcode;
+
+    if (op_type == VIRTIO_CRYPTO_SYM_OP_CIPHER) {
+        virtio_crypto_cipher_session_helper(vdev, &info,
+                           &sess_req->u.cipher.para,
+                           &sess_req->u.cipher.out);
+        /* calculate the offset of input data */
+        input_offset = offsetof(struct virtio_crypto_op_ctrl_req,
+                          u.sym_create_session.u.cipher.input);
+        input = (void *)iov[0].iov_base + input_offset;
+    } else if (op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
+        /* cipher part */
+        virtio_crypto_cipher_session_helper(vdev, &info,
+                           &sess_req->u.chain.para.cipher_param,
+                           &sess_req->u.chain.out.cipher);
+        /* calculate the offset of input data */
+        input_offset = offsetof(struct virtio_crypto_op_ctrl_req,
+                                u.sym_create_session.u.chain.input);
+        input = (void *)iov[0].iov_base + input_offset;
+        /* hash part */
+        info.alg_chain_order = sess_req->u.chain.para.alg_chain_order;
+        info.add_len = sess_req->u.chain.para.aad_len;
+        info.hash_mode = sess_req->u.chain.para.hash_mode;
+        if (info.hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_AUTH) {
+            info.hash_alg = sess_req->u.chain.para.u.mac_param.algo;
+            len = info.auth_key_len =
+                       sess_req->u.chain.para.u.mac_param.auth_key_len;
+            info.hash_result_len =
+                    sess_req->u.chain.para.u.mac_param.hash_result_len;
+            /* get auth key */
+            if (len > 0) {
+                DPRINTF("keylen=%" PRIu32 "\n", info.auth_key_len);
+                auth_key_gpa = sess_req->u.chain.out.mac.auth_key_addr;
+                auth_key_hva = cpu_physical_memory_map(auth_key_gpa,
+                               &len, false);
+                info.auth_key = g_malloc(len);
+                memcpy(info.auth_key, auth_key_hva, len);
+                cpu_physical_memory_unmap(auth_key_hva, len, false, len);
+            }
+        } else if (info.hash_mode == VIRTIO_CRYPTO_SYM_HASH_MODE_PLAIN) {
+            info.hash_alg = sess_req->u.chain.para.u.hash_param.algo;
+            info.hash_result_len =
+                   sess_req->u.chain.para.u.hash_param.hash_result_len;
+        } else {
+            /* VIRTIO_CRYPTO_SYM_HASH_MODE_NESTED */
+            error_report("unsupported hash mode");
+            goto err;
+        }
+    } else {
+        /* calculate the offset of input data */
+        input_offset = offsetof(struct virtio_crypto_op_ctrl_req,
+                                u.sym_create_session.u.cipher.input);
+        input = (void *)iov[0].iov_base + input_offset;
+        /* VIRTIO_CRYPTO_SYM_OP_NONE */
+        error_report("unsupported cipher type");
+        goto err;
+    }
+
+    queue_index = virtio_crypto_vq2q(queue_id);
+    session_id = qcrypto_cryptodev_backend_sym_create_session(
+                                     vcrypto->cryptodev,
+                                     &info, queue_index, &local_err);
+    if (session_id >= 0) {
+        DPRINTF("create session_id=%" PRIu64 "\n", session_id);
+        /* Set the result, notify the frontend driver soon */
+        input->status = VIRTIO_CRYPTO_OP_OK;
+        input->session_id = session_id;
+
+        g_free(info.cipher_key);
+        g_free(info.auth_key);
+        return 0;
+    } else {
+        if (local_err) {
+            error_report_err(local_err);
+        }
+    }
+
+err:
+    g_free(info.cipher_key);
+    g_free(info.auth_key);
+    input->status = VIRTIO_CRYPTO_OP_ERR;
+    return -1;
+}
+
+static void
+virtio_crypto_handle_close_session(VirtIOCrypto *vcrypto,
+         struct virtio_crypto_destroy_session_req *close_sess_req,
+         uint32_t queue_id,
+         VirtQueueElement *elem)
 {
+    int ret;
+    uint64_t session_id;
+    uint32_t status;
+    struct iovec *iov = elem->in_sg;
+    size_t status_offset;
+    void *in_status_ptr;
+    Error *local_err = NULL;
+
+    session_id = close_sess_req->session_id;
+    DPRINTF("close session, id=%" PRIu64 "\n", session_id);
+
+    ret = qcrypto_cryptodev_backend_sym_close_session(
+              vcrypto->cryptodev, session_id, &local_err);
+    if (ret == 0) {
+        status = VIRTIO_CRYPTO_OP_OK;
+    } else {
+        if (local_err) {
+            error_report_err(local_err);
+        } else {
+            error_report("destroy session failed");
+        }
+        status = VIRTIO_CRYPTO_OP_ERR;
+    }
 
+    /* Calculate the offset of status bits */
+    status_offset = offsetof(struct virtio_crypto_op_ctrl_req,
+                             u.destroy_session.status);
+    in_status_ptr = (void *)iov[0].iov_base + status_offset;
+    /* Set the result, notify the frontend driver soon */
+    memcpy(in_status_ptr, &status, sizeof(status));
+}
+
+static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
+    struct virtio_crypto_op_ctrl_req ctrl;
+    VirtQueueElement *elem;
+    size_t s;
+    struct iovec *iov;
+    unsigned int iov_cnt;
+    uint32_t queue_id;
+    uint32_t opcode;
+
+    for (;;) {
+        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
+        if (!elem) {
+            break;
+        }
+        if (elem->in_num < 1 ||
+            iov_size(elem->in_sg, elem->in_num) < sizeof(ctrl)) {
+            error_report("virtio-crypto ctrl missing headers");
+            exit(1);
+        }
+
+        iov_cnt = elem->in_num;
+        iov = elem->in_sg;
+        s = iov_to_buf(iov, iov_cnt, 0, &ctrl, sizeof(ctrl));
+        assert(s == sizeof(ctrl));
+        opcode = ctrl.header.opcode;
+        queue_id = ctrl.header.queue_id;
+
+        switch (opcode) {
+        case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
+            virtio_crypto_create_sym_session(vcrypto,
+                             &ctrl.u.sym_create_session,
+                             queue_id, opcode,
+                             elem);
+
+            break;
+        case VIRTIO_CRYPTO_CIPHER_DESTROY_SESSION:
+        case VIRTIO_CRYPTO_HASH_DESTROY_SESSION:
+        case VIRTIO_CRYPTO_MAC_DESTROY_SESSION:
+        case VIRTIO_CRYPTO_AEAD_DESTROY_SESSION:
+            virtio_crypto_handle_close_session(vcrypto,
+                   &ctrl.u.destroy_session, queue_id,
+                   elem);
+            break;
+        case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
+        case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
+        case VIRTIO_CRYPTO_AEAD_CREATE_SESSION:
+        default:
+            error_report("virtio-crypto unsupported ctrl opcode: %u",
+                         opcode);
+            exit(1);
+        }
+
+        virtqueue_push(vq, elem, sizeof(ctrl));
+        virtio_notify(vdev, vq);
+        g_free(elem);
+    }
 }
 
 static void virtio_crypto_handle_dataq(VirtIODevice *vdev, VirtQueue *vq)
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 09/10] virtio-crypto: add data queue processing handler
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (7 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 08/10] virtio-crypto: add control queue handler Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 10/10] cryptodev: introduce an unified wrapper for crypto operation Gonglei
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

Firstly I introduce VirtIOCryptoReq structure to store
crypto request so that we can support sync and async
crypto operation in the future.

Secondly, VirtIOCryptoBuffer structure is used to
support sg list on source data, destionation data and
associated anthentication data according virtio
crypto sepcification.

At present, we only support cipher and algorithm
chainning.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 hw/virtio/virtio-crypto.c         | 438 ++++++++++++++++++++++++++++++++++++++
 include/hw/virtio/virtio-crypto.h |  11 +
 2 files changed, 449 insertions(+)

diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index 4318327..a82a06e 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -261,9 +261,447 @@ static void virtio_crypto_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
     }
 }
 
+static void virtio_crypto_init_request(VirtIOCrypto *vcrypto, VirtQueue *vq,
+                                VirtIOCryptoReq *req)
+{
+    req->vcrypto = vcrypto;
+    req->vq = vq;
+    req->idata_hva = NULL;
+}
+
+static void virtio_crypto_free_request(VirtIOCryptoReq *req)
+{
+    if (req) {
+        if (req->flags == QCRYPTO_CRYPTODEV_BACKEND_ALG_SYM) {
+            g_free(req->u.sym_op_info);
+        }
+        g_free(req);
+    }
+}
+
+static void
+virtio_crypto_sym_input_data_helper(VirtIODevice *vdev,
+                void *idata_hva,
+                uint32_t status,
+                QCryptoCryptoDevBackendSymOpInfo *sym_op_info);
+
+static void virtio_crypto_req_complete(VirtIOCryptoReq *req, uint32_t status)
+{
+    VirtIOCrypto *vcrypto = req->vcrypto;
+    VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
+
+    if (req->flags == QCRYPTO_CRYPTODEV_BACKEND_ALG_SYM) {
+        virtio_crypto_sym_input_data_helper(vdev, req->idata_hva, status,
+                                            req->u.sym_op_info);
+    }
+
+    virtqueue_push(req->vq, &req->elem,
+                   sizeof(struct virtio_crypto_op_data_req));
+    virtio_notify(vdev, req->vq);
+}
+
+static VirtIOCryptoReq *
+virtio_crypto_get_request(VirtIOCrypto *s, VirtQueue *vq)
+{
+    VirtIOCryptoReq *req = virtqueue_pop(vq, sizeof(VirtIOCryptoReq));
+
+    if (req) {
+        virtio_crypto_init_request(s, vq, req);
+    }
+    return req;
+}
+
+static void virtio_crypto_map_iovec(unsigned int *p_num_sg, hwaddr *addr,
+                               struct iovec *iov,
+                               unsigned int max_num_sg,
+                               hwaddr pa, size_t sz,
+                               bool is_write)
+{
+    unsigned num_sg = *p_num_sg;
+    assert(num_sg <= max_num_sg);
+
+    if (!sz) {
+        error_report("virtio-crypto: zero sized buffers are not allowed");
+        exit(1);
+    }
+
+    while (sz) {
+        hwaddr len = sz;
+
+        if (num_sg == max_num_sg) {
+            error_report("virtio-crypto: too many entries "
+                        "in the scatter gather list");
+            exit(1);
+        }
+
+        iov[num_sg].iov_base = cpu_physical_memory_map(pa, &len, is_write);
+        iov[num_sg].iov_len = len;
+        addr[num_sg] = pa;
+
+        sz -= len;
+        pa += len;
+        num_sg++;
+    }
+    *p_num_sg = num_sg;
+}
+
+static void virtio_crypto_unmap_iovec(VirtIOCryptoBuffer *buf,
+                               unsigned int len,
+                               bool is_write)
+{
+    unsigned int offset;
+    int i;
+
+    if (is_write) {
+        offset = 0;
+        for (i = 0; i < buf->num; i++) {
+            size_t size = MIN(len - offset, buf->sg[i].iov_len);
+
+            cpu_physical_memory_unmap(buf->sg[i].iov_base,
+                                      buf->sg[i].iov_len,
+                                      1, size);
+
+            offset += size;
+        }
+    } else {
+        for (i = 0; i < buf->num; i++) {
+            cpu_physical_memory_unmap(buf->sg[i].iov_base,
+                                      buf->sg[i].iov_len,
+                                      0, buf->sg[i].iov_len);
+        }
+    }
+}
+
+static void *virtio_crypto_read_next_iovec(VirtIODevice *vdev,
+                                struct virtio_crypto_iovec *iovec,
+                                bool is_write,
+                                struct iovec *iov,
+                                unsigned int *num)
+{
+    struct virtio_crypto_iovec *iovec_hva;
+    hwaddr pa;
+    hwaddr len;
+
+    /* If this descriptor says it doesn't chain, we're done. */
+    if (!(iovec->flags & VIRTIO_CRYPTO_IOVEC_F_NEXT)) {
+        return NULL;
+    }
+
+    pa = iovec->next_iovec;
+    len = sizeof(*iovec_hva);
+    iovec_hva = cpu_physical_memory_map(pa, &len, is_write);
+    assert(len == sizeof(*iovec_hva));
+
+    iov[*num].iov_base = iovec_hva;
+    iov[*num].iov_len = len;
+    (*num)++;
+
+    return iovec_hva;
+}
+
+static void *virtio_crypto_alloc_buf(unsigned num)
+{
+    VirtIOCryptoBuffer *buf;
+    size_t addr_ofs = QEMU_ALIGN_UP(sizeof(*buf), __alignof__(buf->addr[0]));
+    size_t addr_end = addr_ofs + num * sizeof(buf->addr[0]);
+    size_t sg_ofs = QEMU_ALIGN_UP(addr_end, __alignof__(buf->sg[0]));
+    size_t sg_end = sg_ofs + num * sizeof(buf->sg[0]);
+
+    buf = g_malloc(sg_end);
+    buf->num = num;
+
+    buf->addr = (void *)buf + addr_ofs;
+    buf->sg = (void *)buf + sg_ofs;
+    return buf;
+}
+
+static void *virtio_crypto_iovec_read(VirtIODevice *vdev,
+                      struct virtio_crypto_iovec *iovec,
+                      bool is_write)
+{
+
+    VirtIOCryptoBuffer *buf;
+    hwaddr addr[VIRTIO_CRYPTO_SG_MAX];
+    struct iovec iov[VIRTIO_CRYPTO_SG_MAX];
+    unsigned int num = 0;
+    /* Save virtio_crypto_iov structure's hva information in sg_list */
+    struct iovec vc_iov[VIRTIO_CRYPTO_SG_MAX];
+    unsigned int vc_num = 0;
+    unsigned int i;
+
+    struct virtio_crypto_iovec *p_iovec = iovec;
+
+    /* Collect all the sgs */
+    do {
+        virtio_crypto_map_iovec(&num, addr, iov,
+                           VIRTIO_CRYPTO_SG_MAX,
+                           p_iovec->addr, p_iovec->len,
+                           is_write);
+    } while ((p_iovec = virtio_crypto_read_next_iovec(vdev,
+                p_iovec, false, vc_iov, &vc_num))
+                != NULL);
+
+    /* Now copy what we have collected and mapped */
+    buf = virtio_crypto_alloc_buf(num);
+    for (i = 0; i < num; i++) {
+        buf->addr[i] = addr[i];
+        buf->sg[i] = iov[i];
+    }
+    /* Unmap all virtio_crypto_iov structure if exists */
+    for (i = 0; i < vc_num; i++) {
+        cpu_physical_memory_unmap(vc_iov[i].iov_base,
+                                  vc_iov[i].iov_len,
+                                  false, vc_iov[i].iov_len);
+    }
+
+    return buf;
+}
+
+static QCryptoCryptoDevBackendSymOpInfo *
+virtio_crypto_cipher_op_helper(VirtIODevice *vdev,
+           struct virtio_crypto_cipher_para *para,
+           struct virtio_crypto_cipher_output *out,
+           struct virtio_crypto_iovec *add_data)
+{
+    QCryptoCryptoDevBackendSymOpInfo *op_info;
+    uint32_t src_len, dst_len;
+    uint32_t iv_len;
+    size_t max_len, curr_size = 0;
+    hwaddr iv_gpa;
+    void *iv_hva;
+    hwaddr len;
+    uint32_t aad_len = 0;
+    VirtIOCryptoBuffer *buf;
+    size_t s;
+
+    iv_len = para->iv_len;
+    src_len = para->src_data_len;
+    dst_len = para->dst_data_len;
+
+    if (add_data) {
+        aad_len = add_data->len;
+    }
+
+    max_len = iv_len + aad_len + src_len + dst_len;
+    op_info = g_malloc0(sizeof(QCryptoCryptoDevBackendSymOpInfo) + max_len);
+    op_info->iv_len = iv_len;
+    op_info->src_len = src_len;
+    op_info->dst_len = dst_len;
+    op_info->aad_len = aad_len;
+    /* handle the initilization vector */
+    if (op_info->iv_len > 0) {
+        len = op_info->iv_len;
+        DPRINTF("iv_len=%" PRIu32 "\n", len);
+        op_info->iv = op_info->data + curr_size;
+
+        iv_gpa = out->iv_addr;
+        iv_hva = cpu_physical_memory_map(iv_gpa, &len, false);
+        memcpy(op_info->iv, iv_hva, len);
+        cpu_physical_memory_unmap(iv_hva, len, false, len);
+        curr_size += len;
+    }
+
+    /* handle additional authentication data if exist */
+    if (op_info->aad_len > 0) {
+        DPRINTF("aad_len=%" PRIu32 "\n", len);
+        op_info->aad_data = op_info->data + curr_size;
+
+        buf = virtio_crypto_iovec_read(vdev, add_data, false);
+        s = iov_to_buf(buf->sg, buf->num, 0, op_info->aad_data,
+                       op_info->aad_len);
+        assert(s == op_info->aad_len);
+
+        virtio_crypto_unmap_iovec(buf, op_info->aad_len, false);
+        g_free(buf);
+        curr_size += op_info->aad_len;
+    }
+
+    /* handle the source data */
+    if (op_info->src_len > 0) {
+        DPRINTF("src_len=%" PRIu32 "\n", op_info->src_len);
+        op_info->src = op_info->data + curr_size;
+
+        buf = virtio_crypto_iovec_read(vdev, &out->src_data, false);
+        s = iov_to_buf(buf->sg, buf->num, 0, op_info->src, op_info->src_len);
+        assert(s == op_info->src_len);
+
+        virtio_crypto_unmap_iovec(buf, op_info->src_len, false);
+        g_free(buf);
+
+        curr_size += op_info->src_len;
+    }
+    op_info->dst = op_info->data + curr_size;
+    DPRINTF("dst_len=%" PRIu32 "\n", op_info->dst_len);
+
+    return op_info;
+}
+
+static void
+virtio_crypto_sym_input_data_helper(VirtIODevice *vdev,
+                void *idata_hva,
+                uint32_t status,
+                QCryptoCryptoDevBackendSymOpInfo *sym_op_info)
+{
+    struct virtio_crypto_sym_input *idata = idata_hva;
+    hwaddr len;
+    VirtIOCryptoBuffer *buf;
+    size_t s;
+
+    idata->status = status;
+    if (status != VIRTIO_CRYPTO_OP_OK) {
+        return;
+    }
+
+    buf = virtio_crypto_iovec_read(vdev, &idata->dst_data, true);
+    /* Note: length of dest_data is equal to length of src_data for cipher */
+    len = sym_op_info->src_len;
+    /* save the cipher result */
+    s = iov_from_buf(buf->sg, buf->num, 0, sym_op_info->dst, len);
+    assert(s == len);
+
+    virtio_crypto_unmap_iovec(buf, len, false);
+    g_free(buf);
+
+    if (sym_op_info->op_type ==
+                      VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
+        hwaddr digest_gpa;
+        void *digest_hva;
+
+        /* save the digest result */
+        digest_gpa = idata->digest_result_addr;
+        len = idata->digest_result_len;
+        if (len != sym_op_info->dst_len - sym_op_info->src_len) {
+            len = sym_op_info->dst_len - sym_op_info->src_len;
+        }
+        digest_hva = cpu_physical_memory_map(digest_gpa, &len, true);
+        /* find the digest result, then copy it into guest's memory */
+        memcpy(digest_hva, sym_op_info->dst + sym_op_info->src_len, len);
+        cpu_physical_memory_unmap(digest_hva, len, true, len);
+    }
+}
+
+static void
+virtio_crypto_handle_sym_req(VirtIOCrypto *vcrypto,
+               struct virtio_crypto_sym_data_req *req,
+               QCryptoCryptoDevBackendSymOpInfo **sym_op_info,
+               void **idata_hva,
+               VirtQueueElement *elem)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(vcrypto);
+    uint32_t op_type;
+    void *idata;
+    size_t idata_offset;
+    struct iovec *iov = elem->in_sg;
+    QCryptoCryptoDevBackendSymOpInfo *op_info;
+
+    op_type = req->op_type;
+
+    if (op_type == VIRTIO_CRYPTO_SYM_OP_CIPHER) {
+        op_info = virtio_crypto_cipher_op_helper(vdev, &req->u.cipher.para,
+                                              &req->u.cipher.odata, NULL);
+        op_info->op_type = op_type;
+        /* calculate the offset of input data */
+        idata_offset = offsetof(struct virtio_crypto_op_data_req,
+                                u.sym_req.u.cipher.idata.input);
+        idata = (void *)iov[0].iov_base + idata_offset;
+    } else if (op_type == VIRTIO_CRYPTO_SYM_OP_ALGORITHM_CHAINING) {
+        /* cipher part */
+        op_info = virtio_crypto_cipher_op_helper(vdev, &req->u.cipher.para,
+                                              &req->u.cipher.odata,
+                                              &req->u.chain.odata.add_data);
+        op_info->op_type = op_type;
+
+        /* calculate the offset of input data */
+        idata_offset = offsetof(struct virtio_crypto_op_data_req,
+                                u.sym_req.u.chain.idata.input);
+        idata = (void *)iov[0].iov_base + idata_offset;
+    } else {
+        /* VIRTIO_CRYPTO_SYM_OP_NONE */
+        error_report("unsupported cipher type");
+        exit(1);
+    }
+
+    *sym_op_info = op_info;
+    *idata_hva = idata;
+}
+
+static void
+virtio_crypto_handle_request(VirtIOCryptoReq *request)
+{
+    VirtIOCrypto *vcrypto = request->vcrypto;
+    VirtQueueElement *elem = &request->elem;
+    int queue_index = virtio_crypto_vq2q(virtio_get_queue_index(request->vq));
+    struct virtio_crypto_op_data_req req;
+    size_t s;
+    int ret;
+    struct iovec *iov;
+    unsigned int iov_cnt;
+    uint32_t opcode, status = VIRTIO_CRYPTO_OP_ERR;
+    uint64_t session_id;
+    QCryptoCryptoDevBackendSymOpInfo *sym_op_info = NULL;
+    void *idata_hva = NULL;
+    Error *local_err = NULL;
+
+    if (elem->in_num < 1 ||
+        iov_size(elem->in_sg, elem->in_num) < sizeof(req)) {
+        error_report("virtio-crypto dataq missing headers");
+        exit(1);
+    }
+
+    iov_cnt = elem->in_num;
+    iov = elem->in_sg;
+
+    s = iov_to_buf(iov, iov_cnt, 0, &req, sizeof(req));
+    assert(s == sizeof(req));
+    opcode = req.header.opcode;
+    session_id = req.header.session_id;
+
+    switch (opcode) {
+    case VIRTIO_CRYPTO_CIPHER_ENCRYPT:
+    case VIRTIO_CRYPTO_CIPHER_DECRYPT:
+        virtio_crypto_handle_sym_req(vcrypto,
+                         &req.u.sym_req,
+                         &sym_op_info,
+                         &idata_hva,
+                         elem);
+        sym_op_info->session_id = session_id;
+
+        /* Set request's parameter */
+        request->flags = QCRYPTO_CRYPTODEV_BACKEND_ALG_SYM;
+        request->u.sym_op_info = sym_op_info;
+        request->idata_hva = idata_hva;
+        ret = qcrypto_cryptodev_backend_sym_operation(vcrypto->cryptodev,
+                                sym_op_info, queue_index, &local_err);
+        if (ret < 0) {
+            status = VIRTIO_CRYPTO_OP_ERR;
+            if (local_err) {
+                error_report_err(local_err);
+            }
+        } else { /* ret >= 0 */
+            status = VIRTIO_CRYPTO_OP_OK;
+        }
+        virtio_crypto_req_complete(request, status);
+        virtio_crypto_free_request(request);
+        break;
+    case VIRTIO_CRYPTO_HASH:
+    case VIRTIO_CRYPTO_MAC:
+    case VIRTIO_CRYPTO_AEAD_ENCRYPT:
+    case VIRTIO_CRYPTO_AEAD_DECRYPT:
+    default:
+        error_report("virtio-crypto unsupported dataq opcode: %u",
+                     opcode);
+        exit(1);
+    }
+}
+
 static void virtio_crypto_handle_dataq(VirtIODevice *vdev, VirtQueue *vq)
 {
+    VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(vdev);
+    VirtIOCryptoReq *req;
 
+    while ((req = virtio_crypto_get_request(vcrypto, vq))) {
+        virtio_crypto_handle_request(req);
+    }
 }
 
 static uint64_t virtio_crypto_get_features(VirtIODevice *vdev,
diff --git a/include/hw/virtio/virtio-crypto.h b/include/hw/virtio/virtio-crypto.h
index f6fe2d8..8c36b25 100644
--- a/include/hw/virtio/virtio-crypto.h
+++ b/include/hw/virtio/virtio-crypto.h
@@ -36,6 +36,17 @@ do { printf("virtio_crypto: " fmt , ## __VA_ARGS__); } while (0)
 #define VIRTIO_CRYPTO_GET_PARENT_CLASS(obj) \
         OBJECT_GET_PARENT_CLASS(obj, TYPE_VIRTIO_CRYPTO)
 
+/* Max entries of scatter gather list in one virtio-crypto buffer */
+#define VIRTIO_CRYPTO_SG_MAX 256
+
+typedef struct VirtIOCryptoBuffer {
+    unsigned int num;
+    /* Guest physical address */
+    hwaddr *addr;
+    /* Store host virtual address and length */
+    struct iovec *sg;
+    uint8_t data[0];
+} VirtIOCryptoBuffer;
 
 typedef struct VirtIOCryptoConf {
     QCryptoCryptoDevBackend *cryptodev;
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [Qemu-devel] [PATCH v3 10/10] cryptodev: introduce an unified wrapper for crypto operation
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (8 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 09/10] virtio-crypto: add data queue processing handler Gonglei
@ 2016-09-19  8:16 ` Gonglei
  2016-09-19  8:39 ` [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation no-reply
  2016-09-22  5:53 ` Gonglei (Arei)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei @ 2016-09-19  8:16 UTC (permalink / raw)
  To: qemu-devel, virtio-dev
  Cc: luonengjun, mst, stefanha, pbonzini, berrange, weidong.huang,
	wu.wubin, mike.caraman, agraf, xin.zeng, claudio.fontana, nmorey,
	vincent.jardin, jianjay.zhou, hanweidong, Gonglei

We use an opaque point to the VirtIOCryptoReq which
can support different packets based on different
algorithms.

Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 crypto/cryptodev-gcrypt.c  |  2 +-
 crypto/cryptodev.c         | 28 ++++++++++++++++++++++++++--
 hw/virtio/virtio-crypto.c  | 10 +++++-----
 include/crypto/cryptodev.h | 13 +++++++------
 4 files changed, 39 insertions(+), 14 deletions(-)

diff --git a/crypto/cryptodev-gcrypt.c b/crypto/cryptodev-gcrypt.c
index 66a0e5e..413afa9 100644
--- a/crypto/cryptodev-gcrypt.c
+++ b/crypto/cryptodev-gcrypt.c
@@ -266,7 +266,7 @@ static int qcrypto_cryptodev_backend_gcrypt_sym_operation(
             return -VIRTIO_CRYPTO_OP_ERR;
         }
     }
-    return 0;
+    return VIRTIO_CRYPTO_OP_OK;
 }
 
 static void qcrypto_cryptodev_backend_gcrypt_cleanup(
diff --git a/crypto/cryptodev.c b/crypto/cryptodev.c
index 0b3d55e..23c389b 100644
--- a/crypto/cryptodev.c
+++ b/crypto/cryptodev.c
@@ -30,6 +30,8 @@
 #include "qapi-visit.h"
 #include "qemu/config-file.h"
 #include "qom/object_interfaces.h"
+#include "hw/virtio/virtio-crypto.h"
+
 
 static QTAILQ_HEAD(, QCryptoCryptoDevBackendClientState) crypto_clients;
 
@@ -103,7 +105,7 @@ int qcrypto_cryptodev_backend_sym_close_session(
     return -1;
 }
 
-int qcrypto_cryptodev_backend_sym_operation(
+static int qcrypto_cryptodev_backend_sym_operation(
                  QCryptoCryptoDevBackend *backend,
                  QCryptoCryptoDevBackendSymOpInfo *op_info,
                  uint32_t queue_index, Error **errp)
@@ -115,7 +117,29 @@ int qcrypto_cryptodev_backend_sym_operation(
         return bc->do_sym_op(backend, op_info, queue_index, errp);
     }
 
-    return -1;
+    return -VIRTIO_CRYPTO_OP_ERR;
+}
+
+int qcrypto_cryptodev_backend_crypto_operation(
+                 QCryptoCryptoDevBackend *backend,
+                 void *opaque,
+                 uint32_t queue_index, Error **errp)
+{
+    VirtIOCryptoReq *req = opaque;
+
+    if (req->flags == QCRYPTO_CRYPTODEV_BACKEND_ALG_SYM) {
+        QCryptoCryptoDevBackendSymOpInfo *op_info;
+        op_info = req->u.sym_op_info;
+
+        return qcrypto_cryptodev_backend_sym_operation(backend,
+                         op_info, queue_index, errp);
+    } else {
+        error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "",
+                   req->flags);
+       return -VIRTIO_CRYPTO_OP_NOTSUPP;
+    }
+
+    return -VIRTIO_CRYPTO_OP_ERR;
 }
 
 static void
diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c
index a82a06e..bee5a61 100644
--- a/hw/virtio/virtio-crypto.c
+++ b/hw/virtio/virtio-crypto.c
@@ -670,15 +670,15 @@ virtio_crypto_handle_request(VirtIOCryptoReq *request)
         request->flags = QCRYPTO_CRYPTODEV_BACKEND_ALG_SYM;
         request->u.sym_op_info = sym_op_info;
         request->idata_hva = idata_hva;
-        ret = qcrypto_cryptodev_backend_sym_operation(vcrypto->cryptodev,
-                                sym_op_info, queue_index, &local_err);
+        ret = qcrypto_cryptodev_backend_crypto_operation(vcrypto->cryptodev,
+                                request, queue_index, &local_err);
         if (ret < 0) {
-            status = VIRTIO_CRYPTO_OP_ERR;
+            status = -ret;
             if (local_err) {
                 error_report_err(local_err);
             }
-        } else { /* ret >= 0 */
-            status = VIRTIO_CRYPTO_OP_OK;
+        } else { /* ret == VIRTIO_CRYPTO_OP_OK */
+            status = ret;
         }
         virtio_crypto_req_complete(request, status);
         virtio_crypto_free_request(request);
diff --git a/include/crypto/cryptodev.h b/include/crypto/cryptodev.h
index 7fcdc2f..8dbf613 100644
--- a/include/crypto/cryptodev.h
+++ b/include/crypto/cryptodev.h
@@ -256,20 +256,21 @@ int qcrypto_cryptodev_backend_sym_close_session(
            uint64_t session_id, Error **errp);
 
 /**
- * qcrypto_cryptodev_backend_sym_operation:
+ * qcrypto_cryptodev_backend_crypto_operation:
  * @backend: the cryptodev backend object
- * @op_info: parameters needed by symmetric crypto operation
+ * @opaque: pointer to a VirtIOCryptoReq object
  * @queue_index: queue index of cryptodev backend client
  * @errp: pointer to a NULL-initialized error object
  *
- * Do symmetric crypto operation, such as encryption and
+ * Do crypto operation, such as encryption and
  * decryption
  *
- * Returns: 0 on success, or Negative on error
+ * Returns: VIRTIO_CRYPTO_OP_OK on success,
+ *         or -VIRTIO_CRYPTO_OP_* on error
  */
-int qcrypto_cryptodev_backend_sym_operation(
+int qcrypto_cryptodev_backend_crypto_operation(
                  QCryptoCryptoDevBackend *backend,
-                 QCryptoCryptoDevBackendSymOpInfo *op_info,
+                 void *opaque,
                  uint32_t queue_index, Error **errp);
 
 #endif /* QCRYPTO_CRYPTODEV_H */
-- 
1.7.12.4

^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend Gonglei
@ 2016-09-19  8:29   ` Daniel P. Berrange
  2016-09-19  8:36     ` Gonglei (Arei)
  2016-09-19  8:56   ` Daniel P. Berrange
  1 sibling, 1 reply; 17+ messages in thread
From: Daniel P. Berrange @ 2016-09-19  8:29 UTC (permalink / raw)
  To: Gonglei
  Cc: qemu-devel, virtio-dev, luonengjun, mst, stefanha, pbonzini,
	weidong.huang, wu.wubin, mike.caraman, agraf, xin.zeng,
	claudio.fontana, nmorey, vincent.jardin, jianjay.zhou,
	hanweidong

AFAICT you are not using gcrypt here - you're using QEMU
cipher APIs (which is good). These APIs can be backed by
either nettle or gcrypt though, so the subject is misleading.


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend
  2016-09-19  8:29   ` Daniel P. Berrange
@ 2016-09-19  8:36     ` Gonglei (Arei)
  0 siblings, 0 replies; 17+ messages in thread
From: Gonglei (Arei) @ 2016-09-19  8:36 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: qemu-devel, virtio-dev, Luonengjun, mst, stefanha, pbonzini,
	Huangweidong (C), Wubin (H),
	mike.caraman, agraf, xin.zeng, Claudio Fontana, nmorey,
	vincent.jardin, Zhoujian (jay, Euler), Hanweidong (Randy)

Hi Daniel,


> -----Original Message-----
> From: Daniel P. Berrange [mailto:berrange@redhat.com]
> Sent: Monday, September 19, 2016 4:30 PM
> Subject: Re: [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new
> cryptodev backend
> 
> AFAICT you are not using gcrypt here - you're using QEMU
> cipher APIs (which is good). These APIs can be backed by
> either nettle or gcrypt though, so the subject is misleading.
> 
Oops, thanks for your reminding :)

Will fix in the next version.


Regards,
-Gonglei


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (9 preceding siblings ...)
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 10/10] cryptodev: introduce an unified wrapper for crypto operation Gonglei
@ 2016-09-19  8:39 ` no-reply
  2016-09-22  5:53 ` Gonglei (Arei)
  11 siblings, 0 replies; 17+ messages in thread
From: no-reply @ 2016-09-19  8:39 UTC (permalink / raw)
  To: arei.gonglei
  Cc: famz, qemu-devel, virtio-dev, weidong.huang, claudio.fontana,
	mst, xin.zeng, hanweidong, luonengjun, agraf, nmorey,
	mike.caraman, stefanha, jianjay.zhou, pbonzini, vincent.jardin,
	wu.wubin

Hi,

Your series seems to have some coding style problems. See output below for
more information:

Type: series
Subject: [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation
Message-id: 1474272982-275836-1-git-send-email-arei.gonglei@huawei.com

=== TEST SCRIPT BEGIN ===
#!/bin/bash

BASE=base
n=1
total=$(git log --oneline $BASE.. | wc -l)
failed=0

# Useful git options
git config --local diff.renamelimit 0
git config --local diff.renames True

commits="$(git log --format=%H --reverse $BASE..)"
for c in $commits; do
    echo "Checking PATCH $n/$total: $(git show --no-patch --format=%s $c)..."
    if ! git show $c --format=email | ./scripts/checkpatch.pl --mailback -; then
        failed=1
        echo
    fi
    n=$((n+1))
done

exit $failed
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/1474272982-275836-1-git-send-email-arei.gonglei@huawei.com -> patchew/1474272982-275836-1-git-send-email-arei.gonglei@huawei.com
Switched to a new branch 'test'
8e80cd7 cryptodev: introduce an unified wrapper for crypto operation
8fa7033 virtio-crypto: add data queue processing handler
5b7c750 virtio-crypto: add control queue handler
b5c70fc virtio-crypto: set capacity of algorithms supported
556bc34 virtio-crypto-pci: add virtio crypto pci support
357cb7c virtio-crypto: add virtio crypto device emulation
8ec8cb5 cryptodev: introduce gcrypt lib as a new cryptodev backend
5bf4aad virtio-crypto: introduce virtio_crypto.h
6002d89 cryptodev: add symmetric algorithm operation stuff
c0d5e8b cryptodev: introduce cryptodev backend interface

=== OUTPUT BEGIN ===
Checking PATCH 1/10: cryptodev: introduce cryptodev backend interface...
ERROR: trailing whitespace
#352: FILE: include/crypto/cryptodev.h:140:
+ */                  $

total: 1 errors, 0 warnings, 327 lines checked

Your patch has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

Checking PATCH 2/10: cryptodev: add symmetric algorithm operation stuff...
Checking PATCH 3/10: virtio-crypto: introduce virtio_crypto.h...
Checking PATCH 4/10: cryptodev: introduce gcrypt lib as a new cryptodev backend...
Checking PATCH 5/10: virtio-crypto: add virtio crypto device emulation...
Checking PATCH 6/10: virtio-crypto-pci: add virtio crypto pci support...
Checking PATCH 7/10: virtio-crypto: set capacity of algorithms supported...
Checking PATCH 8/10: virtio-crypto: add control queue handler...
Checking PATCH 9/10: virtio-crypto: add data queue processing handler...
Checking PATCH 10/10: cryptodev: introduce an unified wrapper for crypto operation...
=== OUTPUT END ===

Test command exited with code: 1


---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@freelists.org

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend
  2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend Gonglei
  2016-09-19  8:29   ` Daniel P. Berrange
@ 2016-09-19  8:56   ` Daniel P. Berrange
  2016-09-19  9:02     ` Gonglei (Arei)
  1 sibling, 1 reply; 17+ messages in thread
From: Daniel P. Berrange @ 2016-09-19  8:56 UTC (permalink / raw)
  To: Gonglei
  Cc: qemu-devel, virtio-dev, luonengjun, mst, stefanha, pbonzini,
	weidong.huang, wu.wubin, mike.caraman, agraf, xin.zeng,
	claudio.fontana, nmorey, vincent.jardin, jianjay.zhou,
	hanweidong

On Mon, Sep 19, 2016 at 04:16:16PM +0800, Gonglei wrote:
> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> ---
>  crypto/Makefile.objs      |   1 +
>  crypto/cryptodev-gcrypt.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++
>  qemu-options.hx           |  18 +++
>  3 files changed, 348 insertions(+)
>  create mode 100644 crypto/cryptodev-gcrypt.c
> 
> diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
> index f7f3c4f..bd8aea7 100644
> --- a/crypto/Makefile.objs
> +++ b/crypto/Makefile.objs
> @@ -27,6 +27,7 @@ crypto-obj-y += block.o
>  crypto-obj-y += block-qcow.o
>  crypto-obj-y += block-luks.o
>  crypto-obj-y += cryptodev.o
> +crypto-obj-$(CONFIG_GCRYPT) += cryptodev-gcrypt.o

This can be just crypto-obj-y +=

>  # Let the userspace emulators avoid linking gnutls/etc
>  crypto-aes-obj-y = aes.o
> diff --git a/crypto/cryptodev-gcrypt.c b/crypto/cryptodev-gcrypt.c
> new file mode 100644
> index 0000000..66a0e5e
> --- /dev/null
> +++ b/crypto/cryptodev-gcrypt.c
> +/**
> + * @TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT:
> + * name of backend that uses gcrypt library
> + */
> +#define TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT "cryptodev-backend-gcrypt"

I'd suggest we just call this backend "builtin", so do a
replace of "gcrypt" with "builtin" throughout.

> +static void qcrypto_cryptodev_backend_gcrypt_init(
> +             QCryptoCryptoDevBackend *backend, Error **errp)
> +{
> +    /* Only support one queue */
> +    int queues = MAX(backend->conf.peers.queues, 1);
> +    int i;

Nitpick, I prefer to see 'size_t' for list iterators
that are always positive. Similar comment in other
places in this series using int i

> +    QCryptoCryptoDevBackendClientState *cc;
> +
> +    for (i = 0; i < queues; i++) {
> +        cc = qcrypto_cryptodev_backend_new_client(
> +                  "cryptodev-gcrypt", NULL);
> +        snprintf(cc->info_str, sizeof(cc->info_str),
> +                 "cryptodev-gcrypt%d", i);
> +        cc->queue_index = i;
> +
> +        backend->conf.peers.ccs[i] = cc;
> +    }
> +
> +    backend->conf.crypto_services =
> +                         1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
> +                         1u << VIRTIO_CRYPTO_SERVICE_HASH |
> +                         1u << VIRTIO_CRYPTO_SERVICE_MAC;
> +    backend->conf.cipher_algo_l = 1u << VIRTIO_CRYPTO_CIPHER_AES_CBC;
> +    backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
> +}
> +
> +static int
> +qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(
> +      QCryptoCryptoDevBackendGcrypt *gcrypt)
> +{
> +    int i;
> +
> +    for (i = 0; i < MAX_NUM_SESSIONS; i++) {
> +        if (gcrypt->sessions[i] == NULL) {
> +            return i;
> +        }
> +    }
> +
> +    return -1;
> +}
> +
> +static int qcrypto_cryptodev_backend_gcrypt_create_cipher_session(
> +                    QCryptoCryptoDevBackendGcrypt *gcrypt,
> +                    QCryptoCryptoDevBackendSymSessionInfo *sess_info,
> +                    Error **errp)
> +{
> +    int algo;
> +    int mode;
> +    QCryptoCipher *cipher;
> +    int index;
> +    QCryptoCryptoDevBackendGcryptSession *sess;
> +
> +    if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) {
> +        error_setg(errp, "unsupported optype :%u", sess_info->op_type);
> +        return -1;
> +    }
> +
> +    index = qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(gcrypt);
> +    if (index < 0) {
> +        error_setg(errp, "the total number of created session exceed %u",
> +                  MAX_NUM_SESSIONS);
> +        return -1;
> +    }
> +
> +    switch (sess_info->cipher_alg) {
> +    case VIRTIO_CRYPTO_CIPHER_AES_ECB:
> +        if (sess_info->key_len == 128 / 8) {
> +            algo = QCRYPTO_CIPHER_ALG_AES_128;
> +        } else if (sess_info->key_len == 192 / 8) {
> +            algo = QCRYPTO_CIPHER_ALG_AES_192;
> +        } else if (sess_info->key_len == 256 / 8) {
> +            algo = QCRYPTO_CIPHER_ALG_AES_256;
> +        } else {
> +            error_setg(errp, "unsupported key length :%u",
> +                       sess_info->key_len);
> +            return -1;
> +        }
> +        mode = QCRYPTO_CIPHER_MODE_ECB;
> +        break;
> +    case VIRTIO_CRYPTO_CIPHER_AES_CBC:
> +        if (sess_info->key_len == 128 / 8) {
> +            algo = QCRYPTO_CIPHER_ALG_AES_128;
> +        } else if (sess_info->key_len == 192 / 8) {
> +            algo = QCRYPTO_CIPHER_ALG_AES_192;
> +        } else if (sess_info->key_len == 256 / 8) {
> +            algo = QCRYPTO_CIPHER_ALG_AES_256;
> +        } else {
> +            error_setg(errp, "unsupported key length :%u",
> +                       sess_info->key_len);
> +            return -1;
> +        }
> +        mode = QCRYPTO_CIPHER_MODE_CBC;
> +        break;
> +    case VIRTIO_CRYPTO_CIPHER_AES_CTR:

Although the QEMU cipher.h API does not export CTR mode currently
it should be trivial to add it. So feel free to add a patch at
the start of the series implementing CTR mode in the cipher API.
Both gcrypt and nettle have support for it which is all we need.

> +    default:
> +        error_setg(errp, "unsupported cipher alg :%u",
> +                   sess_info->cipher_alg);
> +        return -1;
> +    }
> +
> +    cipher = qcrypto_cipher_new(algo, mode,
> +                               sess_info->cipher_key,
> +                               sess_info->key_len,
> +                               errp);
> +    if (!cipher) {
> +        return -1;
> +    }
> +
> +    sess = g_new0(QCryptoCryptoDevBackendGcryptSession, 1);
> +    sess->cipher = cipher;
> +    sess->direction = sess_info->direction;
> +    sess->type = sess_info->op_type;
> +
> +    gcrypt->sessions[index] = sess;
> +
> +    return index;
> +}

> +
> +static int64_t qcrypto_cryptodev_backend_gcrypt_sym_create_session(
> +           QCryptoCryptoDevBackend *backend,
> +           QCryptoCryptoDevBackendSymSessionInfo *sess_info,
> +           uint32_t queue_index, Error **errp)
> +{
> +    QCryptoCryptoDevBackendGcrypt *gcrypt =
> +                      QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend);
> +    int64_t session_id = -1;
> +    int ret;
> +
> +    switch (sess_info->op_code) {
> +    case VIRTIO_CRYPTO_CIPHER_CREATE_SESSION:
> +        ret = qcrypto_cryptodev_backend_gcrypt_create_cipher_session(
> +                           gcrypt, sess_info, errp);
> +        if (ret < 0) {
> +            return ret;
> +        } else {
> +            session_id = ret;
> +        }
> +        break;
> +    case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
> +    case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
> +    default:
> +        error_setg(errp, "unsupported opcode :%" PRIu32 "",
> +                   sess_info->op_code);
> +        return -1;
> +    }
> +
> +    return session_id;
> +}
> +
> +static int qcrypto_cryptodev_backend_gcrypt_sym_close_session(
> +           QCryptoCryptoDevBackend *backend,
> +           uint64_t session_id, Error **errp)
> +{
> +    QCryptoCryptoDevBackendGcrypt *gcrypt =
> +                      QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend);
> +
> +    if (session_id >= MAX_NUM_SESSIONS ||
> +              gcrypt->sessions[session_id] == NULL) {
> +        error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
> +                      session_id);
> +        return -1;
> +    }
> +
> +    qcrypto_cipher_free(gcrypt->sessions[session_id]->cipher);
> +    g_free(gcrypt->sessions[session_id]);
> +    gcrypt->sessions[session_id] = NULL;
> +    return 0;
> +}
> +
> +static int qcrypto_cryptodev_backend_gcrypt_sym_operation(
> +                 QCryptoCryptoDevBackend *backend,
> +                 QCryptoCryptoDevBackendSymOpInfo *op_info,
> +                 uint32_t queue_index, Error **errp)
> +{
> +    QCryptoCryptoDevBackendGcrypt *gcrypt =
> +                      QCRYPTO_CRYPTODEV_BACKEND_GCRYPT(backend);
> +    QCryptoCryptoDevBackendGcryptSession *sess;
> +    int ret;
> +
> +    if (op_info->session_id >= MAX_NUM_SESSIONS ||
> +              gcrypt->sessions[op_info->session_id] == NULL) {
> +        error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
> +                   op_info->session_id);
> +        return -VIRTIO_CRYPTO_OP_INVSESS;
> +    }
> +
> +    sess = gcrypt->sessions[op_info->session_id];
> +
> +    ret = qcrypto_cipher_setiv(sess->cipher, op_info->iv,
> +                               op_info->iv_len, errp);
> +    if (ret < 0) {
> +        return -VIRTIO_CRYPTO_OP_ERR;
> +    }
> +
> +    if (sess->direction == VIRTIO_CRYPTO_OP_ENCRYPT) {
> +        ret = qcrypto_cipher_encrypt(sess->cipher, op_info->src,
> +                                     op_info->dst, op_info->src_len, errp);
> +        if (ret < 0) {
> +            return -VIRTIO_CRYPTO_OP_ERR;
> +        }
> +    } else {
> +        ret = qcrypto_cipher_decrypt(sess->cipher, op_info->src,
> +                                     op_info->dst, op_info->src_len, errp);
> +        if (ret < 0) {
> +            return -VIRTIO_CRYPTO_OP_ERR;
> +        }
> +    }
> +    return 0;
> +}


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend
  2016-09-19  8:56   ` Daniel P. Berrange
@ 2016-09-19  9:02     ` Gonglei (Arei)
  0 siblings, 0 replies; 17+ messages in thread
From: Gonglei (Arei) @ 2016-09-19  9:02 UTC (permalink / raw)
  To: Daniel P. Berrange
  Cc: qemu-devel, virtio-dev, Luonengjun, mst, stefanha, pbonzini,
	Huangweidong (C), Wubin (H),
	mike.caraman, agraf, xin.zeng, Claudio Fontana, nmorey,
	vincent.jardin, Zhoujian (jay, Euler), Hanweidong (Randy)


> -----Original Message-----
> From: Daniel P. Berrange [mailto:berrange@redhat.com]
> Sent: Monday, September 19, 2016 4:56 PM
> Subject: Re: [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new
> cryptodev backend
> 
> On Mon, Sep 19, 2016 at 04:16:16PM +0800, Gonglei wrote:
> > Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> > ---
> >  crypto/Makefile.objs      |   1 +
> >  crypto/cryptodev-gcrypt.c | 329
> ++++++++++++++++++++++++++++++++++++++++++++++
> >  qemu-options.hx           |  18 +++
> >  3 files changed, 348 insertions(+)
> >  create mode 100644 crypto/cryptodev-gcrypt.c
> >
> > diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
> > index f7f3c4f..bd8aea7 100644
> > --- a/crypto/Makefile.objs
> > +++ b/crypto/Makefile.objs
> > @@ -27,6 +27,7 @@ crypto-obj-y += block.o
> >  crypto-obj-y += block-qcow.o
> >  crypto-obj-y += block-luks.o
> >  crypto-obj-y += cryptodev.o
> > +crypto-obj-$(CONFIG_GCRYPT) += cryptodev-gcrypt.o
> 
> This can be just crypto-obj-y +=
> 
Yes.

> >  # Let the userspace emulators avoid linking gnutls/etc
> >  crypto-aes-obj-y = aes.o
> > diff --git a/crypto/cryptodev-gcrypt.c b/crypto/cryptodev-gcrypt.c
> > new file mode 100644
> > index 0000000..66a0e5e
> > --- /dev/null
> > +++ b/crypto/cryptodev-gcrypt.c
> > +/**
> > + * @TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT:
> > + * name of backend that uses gcrypt library
> > + */
> > +#define TYPE_QCRYPTO_CRYPTODEV_BACKEND_GCRYPT
> "cryptodev-backend-gcrypt"
> 
> I'd suggest we just call this backend "builtin", so do a
> replace of "gcrypt" with "builtin" throughout.
> 
OK, good name ;)

> > +static void qcrypto_cryptodev_backend_gcrypt_init(
> > +             QCryptoCryptoDevBackend *backend, Error **errp)
> > +{
> > +    /* Only support one queue */
> > +    int queues = MAX(backend->conf.peers.queues, 1);
> > +    int i;
> 
> Nitpick, I prefer to see 'size_t' for list iterators
> that are always positive. Similar comment in other
> places in this series using int i
> 
OK

> > +    QCryptoCryptoDevBackendClientState *cc;
> > +
> > +    for (i = 0; i < queues; i++) {
> > +        cc = qcrypto_cryptodev_backend_new_client(
> > +                  "cryptodev-gcrypt", NULL);
> > +        snprintf(cc->info_str, sizeof(cc->info_str),
> > +                 "cryptodev-gcrypt%d", i);
> > +        cc->queue_index = i;
> > +
> > +        backend->conf.peers.ccs[i] = cc;
> > +    }
> > +
> > +    backend->conf.crypto_services =
> > +                         1u << VIRTIO_CRYPTO_SERVICE_CIPHER |
> > +                         1u << VIRTIO_CRYPTO_SERVICE_HASH |
> > +                         1u << VIRTIO_CRYPTO_SERVICE_MAC;
> > +    backend->conf.cipher_algo_l = 1u <<
> VIRTIO_CRYPTO_CIPHER_AES_CBC;
> > +    backend->conf.hash_algo = 1u << VIRTIO_CRYPTO_HASH_SHA1;
> > +}
> > +
> > +static int
> > +qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(
> > +      QCryptoCryptoDevBackendGcrypt *gcrypt)
> > +{
> > +    int i;
> > +
> > +    for (i = 0; i < MAX_NUM_SESSIONS; i++) {
> > +        if (gcrypt->sessions[i] == NULL) {
> > +            return i;
> > +        }
> > +    }
> > +
> > +    return -1;
> > +}
> > +
> > +static int qcrypto_cryptodev_backend_gcrypt_create_cipher_session(
> > +                    QCryptoCryptoDevBackendGcrypt *gcrypt,
> > +                    QCryptoCryptoDevBackendSymSessionInfo
> *sess_info,
> > +                    Error **errp)
> > +{
> > +    int algo;
> > +    int mode;
> > +    QCryptoCipher *cipher;
> > +    int index;
> > +    QCryptoCryptoDevBackendGcryptSession *sess;
> > +
> > +    if (sess_info->op_type != VIRTIO_CRYPTO_SYM_OP_CIPHER) {
> > +        error_setg(errp, "unsupported optype :%u", sess_info->op_type);
> > +        return -1;
> > +    }
> > +
> > +    index =
> qcrypto_cryptodev_backend_gcrypt_get_unused_session_index(gcrypt);
> > +    if (index < 0) {
> > +        error_setg(errp, "the total number of created session
> exceed %u",
> > +                  MAX_NUM_SESSIONS);
> > +        return -1;
> > +    }
> > +
> > +    switch (sess_info->cipher_alg) {
> > +    case VIRTIO_CRYPTO_CIPHER_AES_ECB:
> > +        if (sess_info->key_len == 128 / 8) {
> > +            algo = QCRYPTO_CIPHER_ALG_AES_128;
> > +        } else if (sess_info->key_len == 192 / 8) {
> > +            algo = QCRYPTO_CIPHER_ALG_AES_192;
> > +        } else if (sess_info->key_len == 256 / 8) {
> > +            algo = QCRYPTO_CIPHER_ALG_AES_256;
> > +        } else {
> > +            error_setg(errp, "unsupported key length :%u",
> > +                       sess_info->key_len);
> > +            return -1;
> > +        }
> > +        mode = QCRYPTO_CIPHER_MODE_ECB;
> > +        break;
> > +    case VIRTIO_CRYPTO_CIPHER_AES_CBC:
> > +        if (sess_info->key_len == 128 / 8) {
> > +            algo = QCRYPTO_CIPHER_ALG_AES_128;
> > +        } else if (sess_info->key_len == 192 / 8) {
> > +            algo = QCRYPTO_CIPHER_ALG_AES_192;
> > +        } else if (sess_info->key_len == 256 / 8) {
> > +            algo = QCRYPTO_CIPHER_ALG_AES_256;
> > +        } else {
> > +            error_setg(errp, "unsupported key length :%u",
> > +                       sess_info->key_len);
> > +            return -1;
> > +        }
> > +        mode = QCRYPTO_CIPHER_MODE_CBC;
> > +        break;
> > +    case VIRTIO_CRYPTO_CIPHER_AES_CTR:
> 
> Although the QEMU cipher.h API does not export CTR mode currently
> it should be trivial to add it. So feel free to add a patch at
> the start of the series implementing CTR mode in the cipher API.
> Both gcrypt and nettle have support for it which is all we need.
> 
OK, will do.

Thanks,
-Gonglei

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation
  2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
                   ` (10 preceding siblings ...)
  2016-09-19  8:39 ` [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation no-reply
@ 2016-09-22  5:53 ` Gonglei (Arei)
  11 siblings, 0 replies; 17+ messages in thread
From: Gonglei (Arei) @ 2016-09-22  5:53 UTC (permalink / raw)
  To: Gonglei (Arei), qemu-devel, virtio-dev
  Cc: Luonengjun, mst, stefanha, pbonzini, berrange, Huangweidong (C),
	Wubin (H),
	mike.caraman, agraf, xin.zeng, Claudio Fontana, nmorey,
	vincent.jardin, Zhoujian (jay, Euler), Hanweidong (Randy)

Hi Michael, Stefan and Paolo,

Would you please help to review virtio stuff in the patch set? Thanks!

Regards,
-Gonglei


> -----Original Message-----
> From: Gonglei (Arei)
> Sent: Monday, September 19, 2016 4:16 PM
> Subject: [PATCH v3 00/10] virtio-crypto: introduce framework and device
> emulation
> 
> Changes since v2:
>  According to Daniel's comments:
>  - drop cryptodev kernel module as a cryptodev backend
>  - rename crypto stuff to cryptodev stuff
>  - change some files' license to GPLv2+
>  - remove cryptodev command line instead of QOM to define the cryptodev
> backend
>  - rename all functions and structures in crypto sub-directory.
>  - add full inline documentation for cryptodev.h
>  And:
>  - drop crypto-queue.c [Paolo]
>  - merge some patches
> 
> Great thanks to Daniel and Paolo. Please review again, thanks!
> 
> Changes since v1:
>  - rmmove mixed endian-ness handler for virtio-crypto device, just
>    use little-endian. [mst]
>  - add sg list support according virtio-crypto spec v10 (will be posted soon).
>  - fix a memory leak in session handler.
>  - add a feature page link in qemu.org
> (http://qemu-project.org/Features/VirtioCrypto)
>  - fix some trivial problems, sush as 's/Since 2.7/Since 2.8/g' in
> qapi-schema.json
>  - rebase the latest qemu master tree.
> 
> 
> This patch series realize the framework and emulation of a new
> virtio crypto device, which is similar with virtio net device.
> 
>  - I introduce the cryptodev backend as the client of virtio crypto device
>    which can be realized by different methods, such as
> cryptodev-backend-gcrypt in my series,
>    vhost-crypto kernel module, vhost-user etc.
>  - The patch set abides by the virtio crypto speccification.
>  - The virtio crypto support symmetric algorithms (including CIPHER and
> algorithm chainning)
>    at present, except HASH, MAC and AEAD services.
>  - unsupport hot plug/unplug cryptodev backend at this moment.
> 
> Firstly build QEMU with libgcrypt cryptography support.
> 
> QEMU can then be started using the following parameters:
> 
> qemu-system-x86_64 \
>     [...] \
>         -object cryptodev-backend-gcrypt,id=cryptodev0 \
>         -device virtio-crypto-pci,id=crypto0,cryptodev=cryptodev0 \
>     [...]
> 
> The front-end linux kernel driver (Experimental at present) is publicly accessible
> from:
> 
>    https://github.com/gongleiarei/virtio-crypto-linux-driver.git
> 
> After insmod virtio-crypto.ko, you can use cryptodev-linux test the crypto
> function
> in the guest. For example:
> 
> linux-guest:/home/gonglei/cryptodev-linux/tests # ./cipher -
> requested cipher CRYPTO_AES_CBC, got cbc(aes) with driver
> virtio_crypto_aes_cbc
> AES Test passed
> requested cipher CRYPTO_AES_CBC, got cbc(aes) with driver
> virtio_crypto_aes_cbc
> requested cipher CRYPTO_AES_CBC, got cbc(aes) with driver
> virtio_crypto_aes_cbc
> Test passed
> 
> QEMU code also can be accessible from:
> 
>  https://github.com/gongleiarei/qemu.git
> 
>  branch virtio-crypto
> 
> For more information, please see:
>  http://qemu-project.org/Features/VirtioCrypto
> 
> 
> Gonglei (10):
>   cryptodev: introduce cryptodev backend interface
>   cryptodev: add symmetric algorithm operation stuff
>   virtio-crypto: introduce virtio_crypto.h
>   cryptodev: introduce gcrypt lib as a new cryptodev backend
>   virtio-crypto: add virtio crypto device emulation
>   virtio-crypto-pci: add virtio crypto pci support
>   virtio-crypto: set capacity of algorithms supported
>   virtio-crypto: add control queue handler
>   virtio-crypto: add data queue processing handler
>   cryptodev: introduce an unified wrapper for crypto operation
> 
>  crypto/Makefile.objs                           |   2 +
>  crypto/cryptodev-gcrypt.c                      | 329 +++++++++
>  crypto/cryptodev.c                             | 243 +++++++
>  hw/virtio/Makefile.objs                        |   2 +
>  hw/virtio/virtio-crypto-pci.c                  |  76 +++
>  hw/virtio/virtio-crypto.c                      | 904
> +++++++++++++++++++++++++
>  hw/virtio/virtio-pci.h                         |  15 +
>  include/crypto/cryptodev.h                     | 276 ++++++++
>  include/hw/virtio/virtio-crypto.h              | 100 +++
>  include/standard-headers/linux/virtio_crypto.h | 466 +++++++++++++
>  qemu-options.hx                                |  18 +
>  11 files changed, 2431 insertions(+)
>  create mode 100644 crypto/cryptodev-gcrypt.c
>  create mode 100644 crypto/cryptodev.c
>  create mode 100644 hw/virtio/virtio-crypto-pci.c
>  create mode 100644 hw/virtio/virtio-crypto.c
>  create mode 100644 include/crypto/cryptodev.h
>  create mode 100644 include/hw/virtio/virtio-crypto.h
>  create mode 100644 include/standard-headers/linux/virtio_crypto.h
> 
> --
> 1.7.12.4
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-09-22  5:54 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-19  8:16 [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 01/10] cryptodev: introduce cryptodev backend interface Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 02/10] cryptodev: add symmetric algorithm operation stuff Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 03/10] virtio-crypto: introduce virtio_crypto.h Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 04/10] cryptodev: introduce gcrypt lib as a new cryptodev backend Gonglei
2016-09-19  8:29   ` Daniel P. Berrange
2016-09-19  8:36     ` Gonglei (Arei)
2016-09-19  8:56   ` Daniel P. Berrange
2016-09-19  9:02     ` Gonglei (Arei)
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 05/10] virtio-crypto: add virtio crypto device emulation Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 06/10] virtio-crypto-pci: add virtio crypto pci support Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 07/10] virtio-crypto: set capacity of algorithms supported Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 08/10] virtio-crypto: add control queue handler Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 09/10] virtio-crypto: add data queue processing handler Gonglei
2016-09-19  8:16 ` [Qemu-devel] [PATCH v3 10/10] cryptodev: introduce an unified wrapper for crypto operation Gonglei
2016-09-19  8:39 ` [Qemu-devel] [PATCH v3 00/10] virtio-crypto: introduce framework and device emulation no-reply
2016-09-22  5:53 ` Gonglei (Arei)

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.