From d0ee7a135fe499dd900bdca4d70efc2beaa6ef9c Mon Sep 17 00:00:00 2001 From: Gonglei Date: Fri, 28 Oct 2016 16:33:20 +0800 Subject: cryptodev: introduce cryptodev backend interface 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 Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- backends/cryptodev.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 backends/cryptodev.c (limited to 'backends/cryptodev.c') diff --git a/backends/cryptodev.c b/backends/cryptodev.c new file mode 100644 index 0000000000..e8582cdc32 --- /dev/null +++ b/backends/cryptodev.c @@ -0,0 +1,176 @@ +/* + * QEMU Crypto Device Implementation + * + * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD. + * + * Authors: + * Gonglei + * + * 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 . + * + */ + +#include "qemu/osdep.h" +#include "sysemu/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(, CryptoDevBackendClient) crypto_clients; + + +CryptoDevBackendClient * +cryptodev_backend_new_client(const char *model, + const char *name) +{ + CryptoDevBackendClient *cc; + + cc = g_malloc0(sizeof(CryptoDevBackendClient)); + cc->model = g_strdup(model); + if (name) { + cc->name = g_strdup(name); + } + + QTAILQ_INSERT_TAIL(&crypto_clients, cc, next); + + return cc; +} + +void cryptodev_backend_free_client( + CryptoDevBackendClient *cc) +{ + QTAILQ_REMOVE(&crypto_clients, cc, next); + g_free(cc->name); + g_free(cc->model); + g_free(cc->info_str); + g_free(cc); +} + +void cryptodev_backend_cleanup( + CryptoDevBackend *backend, + Error **errp) +{ + CryptoDevBackendClass *bc = + CRYPTODEV_BACKEND_GET_CLASS(backend); + + if (bc->cleanup) { + bc->cleanup(backend, errp); + } + + backend->ready = false; +} + +static void +cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + CryptoDevBackend *backend = CRYPTODEV_BACKEND(obj); + uint32_t value = backend->conf.peers.queues; + + visit_type_uint32(v, name, &value, errp); +} + +static void +cryptodev_backend_set_queues(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + CryptoDevBackend *backend = 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 +cryptodev_backend_complete(UserCreatable *uc, Error **errp) +{ + CryptoDevBackend *backend = CRYPTODEV_BACKEND(uc); + CryptoDevBackendClass *bc = CRYPTODEV_BACKEND_GET_CLASS(uc); + Error *local_err = NULL; + + if (bc->init) { + bc->init(backend, &local_err); + if (local_err) { + goto out; + } + } + backend->ready = true; + return; + +out: + backend->ready = false; + error_propagate(errp, local_err); +} + +static void cryptodev_backend_instance_init(Object *obj) +{ + object_property_add(obj, "queues", "int", + cryptodev_backend_get_queues, + cryptodev_backend_set_queues, + NULL, NULL, NULL); + /* Initialize devices' queues property to 1 */ + object_property_set_int(obj, 1, "queues", NULL); +} + +static void cryptodev_backend_finalize(Object *obj) +{ + +} + +static void +cryptodev_backend_class_init(ObjectClass *oc, void *data) +{ + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc); + + ucc->complete = cryptodev_backend_complete; + + QTAILQ_INIT(&crypto_clients); +} + +static const TypeInfo cryptodev_backend_info = { + .name = TYPE_CRYPTODEV_BACKEND, + .parent = TYPE_OBJECT, + .instance_size = sizeof(CryptoDevBackend), + .instance_init = cryptodev_backend_instance_init, + .instance_finalize = cryptodev_backend_finalize, + .class_size = sizeof(CryptoDevBackendClass), + .class_init = cryptodev_backend_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_USER_CREATABLE }, + { } + } +}; + +static void +cryptodev_backend_register_types(void) +{ + type_register_static(&cryptodev_backend_info); +} + +type_init(cryptodev_backend_register_types); -- cgit 1.4.1 From 9e4f86a84ea2abfd85c46829310d9bdd563648e1 Mon Sep 17 00:00:00 2001 From: Gonglei Date: Fri, 28 Oct 2016 16:33:21 +0800 Subject: cryptodev: add symmetric algorithm operation stuff This patch adds session operation and crypto operation stuff in the cryptodev backend, including function pointers and corresponding structures. Signed-off-by: Gonglei Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- backends/cryptodev.c | 45 ++++++++++++++ include/sysemu/cryptodev.h | 149 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) (limited to 'backends/cryptodev.c') diff --git a/backends/cryptodev.c b/backends/cryptodev.c index e8582cdc32..47521cf963 100644 --- a/backends/cryptodev.c +++ b/backends/cryptodev.c @@ -75,6 +75,51 @@ void cryptodev_backend_cleanup( backend->ready = false; } +int64_t cryptodev_backend_sym_create_session( + CryptoDevBackend *backend, + CryptoDevBackendSymSessionInfo *sess_info, + uint32_t queue_index, Error **errp) +{ + CryptoDevBackendClass *bc = + CRYPTODEV_BACKEND_GET_CLASS(backend); + + if (bc->create_session) { + return bc->create_session(backend, sess_info, queue_index, errp); + } + + return -1; +} + +int cryptodev_backend_sym_close_session( + CryptoDevBackend *backend, + uint64_t session_id, + uint32_t queue_index, Error **errp) +{ + CryptoDevBackendClass *bc = + CRYPTODEV_BACKEND_GET_CLASS(backend); + + if (bc->close_session) { + return bc->close_session(backend, session_id, queue_index, errp); + } + + return -1; +} + +int cryptodev_backend_sym_operation( + CryptoDevBackend *backend, + CryptoDevBackendSymOpInfo *op_info, + uint32_t queue_index, Error **errp) +{ + CryptoDevBackendClass *bc = + 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 cryptodev_backend_get_queues(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) diff --git a/include/sysemu/cryptodev.h b/include/sysemu/cryptodev.h index bfaf77107b..e66bd4b3c0 100644 --- a/include/sysemu/cryptodev.h +++ b/include/sysemu/cryptodev.h @@ -56,12 +56,111 @@ typedef struct CryptoDevBackendClient CryptoDevBackendClient; typedef struct CryptoDevBackend CryptoDevBackend; +enum CryptoDevBackendAlgType { + CRYPTODEV_BACKEND_ALG_SYM, + CRYPTODEV_BACKEND_ALG__MAX, +}; + +/** + * CryptoDevBackendSymSessionInfo: + * + * @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: point to a key of CIPHER + * @auth_key: point to an authenticated key of MAC + * + */ +typedef struct CryptoDevBackendSymSessionInfo { + /* 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; +} CryptoDevBackendSymSessionInfo; + +/** + * CryptoDevBackendSymOpInfo: + * + * @session_id: session index which was previously + * created by cryptodev_backend_sym_create_session() + * @aad_len: byte length of additional authenticated data + * @iv_len: byte length of initialization vector or counter + * @src_len: byte length of source data + * @dst_len: byte length of destination data + * @digest_result_len: byte length of hash digest result + * @hash_start_src_offset: Starting point for hash processing, specified + * as number of bytes from start of packet in source data, only used for + * algorithm chain + * @cipher_start_src_offset: Starting point for cipher processing, specified + * as number of bytes from start of packet in source data, only used for + * algorithm chain + * @len_to_hash: byte length of source data on which the hash + * operation will be computed, only used for algorithm chain + * @len_to_cipher: byte length of source data on which the cipher + * operation will be computed, only used for algorithm chain + * @op_type: operation type (refer to virtio_crypto.h) + * @iv: point to the initialization vector or counter + * @src: point to the source data + * @dst: point to the destination data + * @aad_data: point to the additional authenticated data + * @digest_result: point to the digest result data + * @data[0]: point to the extensional memory by one memory allocation + * + */ +typedef struct CryptoDevBackendSymOpInfo { + uint64_t session_id; + uint32_t aad_len; + uint32_t iv_len; + uint32_t src_len; + uint32_t dst_len; + uint32_t digest_result_len; + uint32_t hash_start_src_offset; + uint32_t cipher_start_src_offset; + uint32_t len_to_hash; + uint32_t len_to_cipher; + uint8_t op_type; + uint8_t *iv; + uint8_t *src; + uint8_t *dst; + uint8_t *aad_data; + uint8_t *digest_result; + uint8_t data[0]; +} CryptoDevBackendSymOpInfo; typedef struct CryptoDevBackendClass { ObjectClass parent_class; void (*init)(CryptoDevBackend *backend, Error **errp); void (*cleanup)(CryptoDevBackend *backend, Error **errp); + + int64_t (*create_session)(CryptoDevBackend *backend, + CryptoDevBackendSymSessionInfo *sess_info, + uint32_t queue_index, Error **errp); + int (*close_session)(CryptoDevBackend *backend, + uint64_t session_id, + uint32_t queue_index, Error **errp); + int (*do_sym_op)(CryptoDevBackend *backend, + CryptoDevBackendSymOpInfo *op_info, + uint32_t queue_index, Error **errp); } CryptoDevBackendClass; @@ -145,4 +244,54 @@ void cryptodev_backend_cleanup( CryptoDevBackend *backend, Error **errp); +/** + * 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 cryptodev_backend_sym_create_session( + CryptoDevBackend *backend, + CryptoDevBackendSymSessionInfo *sess_info, + uint32_t queue_index, Error **errp); + +/** + * cryptodev_backend_sym_close_session: + * @backend: the cryptodev backend object + * @session_id: the session id + * @queue_index: queue index of cryptodev backend client + * @errp: pointer to a NULL-initialized error object + * + * Close a session for symmetric algorithms which was previously + * created by cryptodev_backend_sym_create_session() + * + * Returns: 0 on success, or Negative on error + */ +int cryptodev_backend_sym_close_session( + CryptoDevBackend *backend, + uint64_t session_id, + uint32_t queue_index, Error **errp); + +/** + * 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 cryptodev_backend_sym_operation( + CryptoDevBackend *backend, + CryptoDevBackendSymOpInfo *op_info, + uint32_t queue_index, Error **errp); + #endif /* CRYPTODEV_H */ -- cgit 1.4.1 From d6634ac09abf20d890fd094773f125ee0ff0b1cb Mon Sep 17 00:00:00 2001 From: Gonglei Date: Fri, 28 Oct 2016 16:33:29 +0800 Subject: cryptodev: introduce an unified wrapper for crypto operation We use an opaque point to the VirtIOCryptoReq which can support different packets based on different algorithms. Signed-off-by: Gonglei Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- backends/cryptodev.c | 28 ++++++++++++++++++++++++++-- hw/virtio/virtio-crypto.c | 10 +++++----- include/sysemu/cryptodev.h | 13 +++++++------ 3 files changed, 38 insertions(+), 13 deletions(-) (limited to 'backends/cryptodev.c') diff --git a/backends/cryptodev.c b/backends/cryptodev.c index 47521cf963..4a49f9762f 100644 --- a/backends/cryptodev.c +++ b/backends/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(, CryptoDevBackendClient) crypto_clients; @@ -105,7 +107,7 @@ int cryptodev_backend_sym_close_session( return -1; } -int cryptodev_backend_sym_operation( +static int cryptodev_backend_sym_operation( CryptoDevBackend *backend, CryptoDevBackendSymOpInfo *op_info, uint32_t queue_index, Error **errp) @@ -117,7 +119,29 @@ int cryptodev_backend_sym_operation( return bc->do_sym_op(backend, op_info, queue_index, errp); } - return -1; + return -VIRTIO_CRYPTO_ERR; +} + +int cryptodev_backend_crypto_operation( + CryptoDevBackend *backend, + void *opaque, + uint32_t queue_index, Error **errp) +{ + VirtIOCryptoReq *req = opaque; + + if (req->flags == CRYPTODEV_BACKEND_ALG_SYM) { + CryptoDevBackendSymOpInfo *op_info; + op_info = req->u.sym_op_info; + + return cryptodev_backend_sym_operation(backend, + op_info, queue_index, errp); + } else { + error_setg(errp, "Unsupported cryptodev alg type: %" PRIu32 "", + req->flags); + return -VIRTIO_CRYPTO_NOTSUPP; + } + + return -VIRTIO_CRYPTO_ERR; } static void diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index 454384fa7d..c160aa4f15 100644 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -634,15 +634,15 @@ virtio_crypto_handle_request(VirtIOCryptoReq *request) /* Set request's parameter */ request->flags = CRYPTODEV_BACKEND_ALG_SYM; request->u.sym_op_info = sym_op_info; - ret = cryptodev_backend_sym_operation(vcrypto->cryptodev, - sym_op_info, queue_index, &local_err); + ret = cryptodev_backend_crypto_operation(vcrypto->cryptodev, + request, queue_index, &local_err); if (ret < 0) { - status = VIRTIO_CRYPTO_ERR; + status = -ret; if (local_err) { error_report_err(local_err); } - } else { /* ret >= 0 */ - status = VIRTIO_CRYPTO_OK; + } else { /* ret == VIRTIO_CRYPTO_OK */ + status = ret; } virtio_crypto_req_complete(request, status); virtio_crypto_free_request(request); diff --git a/include/sysemu/cryptodev.h b/include/sysemu/cryptodev.h index e66bd4b3c0..84526c0d35 100644 --- a/include/sysemu/cryptodev.h +++ b/include/sysemu/cryptodev.h @@ -278,20 +278,21 @@ int cryptodev_backend_sym_close_session( uint32_t queue_index, Error **errp); /** - * cryptodev_backend_sym_operation: + * 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_OK on success, + * or -VIRTIO_CRYPTO_* on error */ -int cryptodev_backend_sym_operation( +int cryptodev_backend_crypto_operation( CryptoDevBackend *backend, - CryptoDevBackendSymOpInfo *op_info, + void *opaque, uint32_t queue_index, Error **errp); #endif /* CRYPTODEV_H */ -- cgit 1.4.1