From patchwork Mon Sep 19 08:16:20 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Gonglei (Arei)" X-Patchwork-Id: 9338801 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 29C3C6077A for ; Mon, 19 Sep 2016 08:33:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 189562905F for ; Mon, 19 Sep 2016 08:33:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0D0E129149; Mon, 19 Sep 2016 08:33:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3BB1D2905F for ; Mon, 19 Sep 2016 08:33:15 +0000 (UTC) Received: from localhost ([::1]:53661 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1blu0o-0001gR-G1 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 19 Sep 2016 04:33:14 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54630) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bltv7-00060X-NR for qemu-devel@nongnu.org; Mon, 19 Sep 2016 04:27:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bltv4-0004Zo-9H for qemu-devel@nongnu.org; Mon, 19 Sep 2016 04:27:21 -0400 Received: from szxga02-in.huawei.com ([119.145.14.65]:1172) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bltv3-0004ZL-91 for qemu-devel@nongnu.org; Mon, 19 Sep 2016 04:27:18 -0400 Received: from 172.24.1.47 (EHLO szxeml428-hub.china.huawei.com) ([172.24.1.47]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DNH04448; Mon, 19 Sep 2016 16:16:44 +0800 (CST) Received: from localhost (10.177.18.62) by szxeml428-hub.china.huawei.com (10.82.67.183) with Microsoft SMTP Server id 14.3.235.1; Mon, 19 Sep 2016 16:16:36 +0800 From: Gonglei To: , Date: Mon, 19 Sep 2016 16:16:20 +0800 Message-ID: <1474272982-275836-9-git-send-email-arei.gonglei@huawei.com> X-Mailer: git-send-email 2.6.3.windows.1 In-Reply-To: <1474272982-275836-1-git-send-email-arei.gonglei@huawei.com> References: <1474272982-275836-1-git-send-email-arei.gonglei@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.177.18.62] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020206.57DF9EED.001C, ss=1, re=0.000, recu=0.000, reip=0.000, cl=1, cld=1, fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: f0362c68e9db6540d2bb5012921fabcc X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4.x-2.6.x [generic] X-Received-From: 119.145.14.65 Subject: [Qemu-devel] [PATCH v3 08/10] virtio-crypto: add control queue handler X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: weidong.huang@huawei.com, claudio.fontana@huawei.com, mst@redhat.com, xin.zeng@intel.com, hanweidong@huawei.com, luonengjun@huawei.com, agraf@suse.de, nmorey@kalray.eu, mike.caraman@nxp.com, Gonglei , stefanha@redhat.com, jianjay.zhou@huawei.com, pbonzini@redhat.com, vincent.jardin@6wind.com, wu.wubin@huawei.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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)