159ca6c93Szhenwei pi // SPDX-License-Identifier: GPL-2.0-or-later
259ca6c93Szhenwei pi /* Asymmetric algorithms supported by virtio crypto device
359ca6c93Szhenwei pi *
459ca6c93Szhenwei pi * Authors: zhenwei pi <pizhenwei@bytedance.com>
559ca6c93Szhenwei pi * lei he <helei.sig11@bytedance.com>
659ca6c93Szhenwei pi *
759ca6c93Szhenwei pi * Copyright 2022 Bytedance CO., LTD.
859ca6c93Szhenwei pi */
959ca6c93Szhenwei pi
107a2673d7SHerbert Xu #include <crypto/engine.h>
1159ca6c93Szhenwei pi #include <crypto/internal/akcipher.h>
1259ca6c93Szhenwei pi #include <crypto/internal/rsa.h>
1359ca6c93Szhenwei pi #include <crypto/scatterwalk.h>
147a2673d7SHerbert Xu #include <linux/err.h>
157a2673d7SHerbert Xu #include <linux/kernel.h>
167a2673d7SHerbert Xu #include <linux/mpi.h>
177a2673d7SHerbert Xu #include <linux/scatterlist.h>
187a2673d7SHerbert Xu #include <linux/slab.h>
197a2673d7SHerbert Xu #include <linux/string.h>
2059ca6c93Szhenwei pi #include <uapi/linux/virtio_crypto.h>
2159ca6c93Szhenwei pi #include "virtio_crypto_common.h"
2259ca6c93Szhenwei pi
2359ca6c93Szhenwei pi struct virtio_crypto_rsa_ctx {
2459ca6c93Szhenwei pi MPI n;
2559ca6c93Szhenwei pi };
2659ca6c93Szhenwei pi
2759ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx {
2859ca6c93Szhenwei pi struct virtio_crypto *vcrypto;
2959ca6c93Szhenwei pi struct crypto_akcipher *tfm;
3059ca6c93Szhenwei pi bool session_valid;
3159ca6c93Szhenwei pi __u64 session_id;
3259ca6c93Szhenwei pi union {
3359ca6c93Szhenwei pi struct virtio_crypto_rsa_ctx rsa_ctx;
3459ca6c93Szhenwei pi };
3559ca6c93Szhenwei pi };
3659ca6c93Szhenwei pi
3759ca6c93Szhenwei pi struct virtio_crypto_akcipher_request {
3859ca6c93Szhenwei pi struct virtio_crypto_request base;
3959ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *akcipher_ctx;
4059ca6c93Szhenwei pi struct akcipher_request *akcipher_req;
4159ca6c93Szhenwei pi void *src_buf;
4259ca6c93Szhenwei pi void *dst_buf;
4359ca6c93Szhenwei pi uint32_t opcode;
4459ca6c93Szhenwei pi };
4559ca6c93Szhenwei pi
4659ca6c93Szhenwei pi struct virtio_crypto_akcipher_algo {
4759ca6c93Szhenwei pi uint32_t algonum;
4859ca6c93Szhenwei pi uint32_t service;
4959ca6c93Szhenwei pi unsigned int active_devs;
507a2673d7SHerbert Xu struct akcipher_engine_alg algo;
5159ca6c93Szhenwei pi };
5259ca6c93Szhenwei pi
5359ca6c93Szhenwei pi static DEFINE_MUTEX(algs_lock);
5459ca6c93Szhenwei pi
virtio_crypto_akcipher_finalize_req(struct virtio_crypto_akcipher_request * vc_akcipher_req,struct akcipher_request * req,int err)5559ca6c93Szhenwei pi static void virtio_crypto_akcipher_finalize_req(
5659ca6c93Szhenwei pi struct virtio_crypto_akcipher_request *vc_akcipher_req,
5759ca6c93Szhenwei pi struct akcipher_request *req, int err)
5859ca6c93Szhenwei pi {
591bedcf22Slei he kfree(vc_akcipher_req->src_buf);
601bedcf22Slei he kfree(vc_akcipher_req->dst_buf);
611bedcf22Slei he vc_akcipher_req->src_buf = NULL;
621bedcf22Slei he vc_akcipher_req->dst_buf = NULL;
6359ca6c93Szhenwei pi virtcrypto_clear_request(&vc_akcipher_req->base);
6459ca6c93Szhenwei pi
6559ca6c93Szhenwei pi crypto_finalize_akcipher_request(vc_akcipher_req->base.dataq->engine, req, err);
6659ca6c93Szhenwei pi }
6759ca6c93Szhenwei pi
virtio_crypto_dataq_akcipher_callback(struct virtio_crypto_request * vc_req,int len)6859ca6c93Szhenwei pi static void virtio_crypto_dataq_akcipher_callback(struct virtio_crypto_request *vc_req, int len)
6959ca6c93Szhenwei pi {
7059ca6c93Szhenwei pi struct virtio_crypto_akcipher_request *vc_akcipher_req =
7159ca6c93Szhenwei pi container_of(vc_req, struct virtio_crypto_akcipher_request, base);
7259ca6c93Szhenwei pi struct akcipher_request *akcipher_req;
7359ca6c93Szhenwei pi int error;
7459ca6c93Szhenwei pi
7559ca6c93Szhenwei pi switch (vc_req->status) {
7659ca6c93Szhenwei pi case VIRTIO_CRYPTO_OK:
7759ca6c93Szhenwei pi error = 0;
7859ca6c93Szhenwei pi break;
7959ca6c93Szhenwei pi case VIRTIO_CRYPTO_INVSESS:
8059ca6c93Szhenwei pi case VIRTIO_CRYPTO_ERR:
8159ca6c93Szhenwei pi error = -EINVAL;
8259ca6c93Szhenwei pi break;
8359ca6c93Szhenwei pi case VIRTIO_CRYPTO_BADMSG:
8459ca6c93Szhenwei pi error = -EBADMSG;
8559ca6c93Szhenwei pi break;
8659ca6c93Szhenwei pi
8759ca6c93Szhenwei pi case VIRTIO_CRYPTO_KEY_REJECTED:
8859ca6c93Szhenwei pi error = -EKEYREJECTED;
8959ca6c93Szhenwei pi break;
9059ca6c93Szhenwei pi
9159ca6c93Szhenwei pi default:
9259ca6c93Szhenwei pi error = -EIO;
9359ca6c93Szhenwei pi break;
9459ca6c93Szhenwei pi }
9559ca6c93Szhenwei pi
9659ca6c93Szhenwei pi akcipher_req = vc_akcipher_req->akcipher_req;
97a36bd0adSlei he if (vc_akcipher_req->opcode != VIRTIO_CRYPTO_AKCIPHER_VERIFY) {
98a36bd0adSlei he /* actuall length maybe less than dst buffer */
99a36bd0adSlei he akcipher_req->dst_len = len - sizeof(vc_req->status);
10059ca6c93Szhenwei pi sg_copy_from_buffer(akcipher_req->dst, sg_nents(akcipher_req->dst),
10159ca6c93Szhenwei pi vc_akcipher_req->dst_buf, akcipher_req->dst_len);
102a36bd0adSlei he }
10359ca6c93Szhenwei pi virtio_crypto_akcipher_finalize_req(vc_akcipher_req, akcipher_req, error);
10459ca6c93Szhenwei pi }
10559ca6c93Szhenwei pi
virtio_crypto_alg_akcipher_init_session(struct virtio_crypto_akcipher_ctx * ctx,struct virtio_crypto_ctrl_header * header,struct virtio_crypto_akcipher_session_para * para,const uint8_t * key,unsigned int keylen)10659ca6c93Szhenwei pi static int virtio_crypto_alg_akcipher_init_session(struct virtio_crypto_akcipher_ctx *ctx,
107*b0365460Szhenwei pi struct virtio_crypto_ctrl_header *header,
108*b0365460Szhenwei pi struct virtio_crypto_akcipher_session_para *para,
10959ca6c93Szhenwei pi const uint8_t *key, unsigned int keylen)
11059ca6c93Szhenwei pi {
11159ca6c93Szhenwei pi struct scatterlist outhdr_sg, key_sg, inhdr_sg, *sgs[3];
11259ca6c93Szhenwei pi struct virtio_crypto *vcrypto = ctx->vcrypto;
11359ca6c93Szhenwei pi uint8_t *pkey;
11459ca6c93Szhenwei pi int err;
11559ca6c93Szhenwei pi unsigned int num_out = 0, num_in = 0;
1166fd763d1Szhenwei pi struct virtio_crypto_op_ctrl_req *ctrl;
1176fd763d1Szhenwei pi struct virtio_crypto_session_input *input;
1180756ad15Szhenwei pi struct virtio_crypto_ctrl_request *vc_ctrl_req;
11959ca6c93Szhenwei pi
1204409c08dSChristophe JAILLET pkey = kmemdup(key, keylen, GFP_KERNEL);
12159ca6c93Szhenwei pi if (!pkey)
12259ca6c93Szhenwei pi return -ENOMEM;
12359ca6c93Szhenwei pi
1240756ad15Szhenwei pi vc_ctrl_req = kzalloc(sizeof(*vc_ctrl_req), GFP_KERNEL);
1250756ad15Szhenwei pi if (!vc_ctrl_req) {
1260756ad15Szhenwei pi err = -ENOMEM;
1270756ad15Szhenwei pi goto out;
1280756ad15Szhenwei pi }
1290756ad15Szhenwei pi
1300756ad15Szhenwei pi ctrl = &vc_ctrl_req->ctrl;
1316fd763d1Szhenwei pi memcpy(&ctrl->header, header, sizeof(ctrl->header));
132*b0365460Szhenwei pi memcpy(&ctrl->u.akcipher_create_session.para, para, sizeof(*para));
1330756ad15Szhenwei pi input = &vc_ctrl_req->input;
1346fd763d1Szhenwei pi input->status = cpu_to_le32(VIRTIO_CRYPTO_ERR);
13559ca6c93Szhenwei pi
1366fd763d1Szhenwei pi sg_init_one(&outhdr_sg, ctrl, sizeof(*ctrl));
13759ca6c93Szhenwei pi sgs[num_out++] = &outhdr_sg;
13859ca6c93Szhenwei pi
13959ca6c93Szhenwei pi sg_init_one(&key_sg, pkey, keylen);
14059ca6c93Szhenwei pi sgs[num_out++] = &key_sg;
14159ca6c93Szhenwei pi
1426fd763d1Szhenwei pi sg_init_one(&inhdr_sg, input, sizeof(*input));
14359ca6c93Szhenwei pi sgs[num_out + num_in++] = &inhdr_sg;
14459ca6c93Szhenwei pi
145977231e8Szhenwei pi err = virtio_crypto_ctrl_vq_request(vcrypto, sgs, num_out, num_in, vc_ctrl_req);
146977231e8Szhenwei pi if (err < 0)
14759ca6c93Szhenwei pi goto out;
14859ca6c93Szhenwei pi
1496fd763d1Szhenwei pi if (le32_to_cpu(input->status) != VIRTIO_CRYPTO_OK) {
1500756ad15Szhenwei pi pr_err("virtio_crypto: Create session failed status: %u\n",
1510756ad15Szhenwei pi le32_to_cpu(input->status));
15259ca6c93Szhenwei pi err = -EINVAL;
15359ca6c93Szhenwei pi goto out;
15459ca6c93Szhenwei pi }
15559ca6c93Szhenwei pi
1566fd763d1Szhenwei pi ctx->session_id = le64_to_cpu(input->session_id);
15759ca6c93Szhenwei pi ctx->session_valid = true;
15859ca6c93Szhenwei pi err = 0;
15959ca6c93Szhenwei pi
16059ca6c93Szhenwei pi out:
1610756ad15Szhenwei pi kfree(vc_ctrl_req);
16259ca6c93Szhenwei pi kfree_sensitive(pkey);
16359ca6c93Szhenwei pi
16459ca6c93Szhenwei pi return err;
16559ca6c93Szhenwei pi }
16659ca6c93Szhenwei pi
virtio_crypto_alg_akcipher_close_session(struct virtio_crypto_akcipher_ctx * ctx)16759ca6c93Szhenwei pi static int virtio_crypto_alg_akcipher_close_session(struct virtio_crypto_akcipher_ctx *ctx)
16859ca6c93Szhenwei pi {
16959ca6c93Szhenwei pi struct scatterlist outhdr_sg, inhdr_sg, *sgs[2];
17059ca6c93Szhenwei pi struct virtio_crypto_destroy_session_req *destroy_session;
17159ca6c93Szhenwei pi struct virtio_crypto *vcrypto = ctx->vcrypto;
172977231e8Szhenwei pi unsigned int num_out = 0, num_in = 0;
17359ca6c93Szhenwei pi int err;
1746fd763d1Szhenwei pi struct virtio_crypto_op_ctrl_req *ctrl;
1756fd763d1Szhenwei pi struct virtio_crypto_inhdr *ctrl_status;
1760756ad15Szhenwei pi struct virtio_crypto_ctrl_request *vc_ctrl_req;
17759ca6c93Szhenwei pi
1780756ad15Szhenwei pi if (!ctx->session_valid)
1790756ad15Szhenwei pi return 0;
1800756ad15Szhenwei pi
1810756ad15Szhenwei pi vc_ctrl_req = kzalloc(sizeof(*vc_ctrl_req), GFP_KERNEL);
1820756ad15Szhenwei pi if (!vc_ctrl_req)
1830756ad15Szhenwei pi return -ENOMEM;
1840756ad15Szhenwei pi
1850756ad15Szhenwei pi ctrl_status = &vc_ctrl_req->ctrl_status;
1866fd763d1Szhenwei pi ctrl_status->status = VIRTIO_CRYPTO_ERR;
1870756ad15Szhenwei pi ctrl = &vc_ctrl_req->ctrl;
1886fd763d1Szhenwei pi ctrl->header.opcode = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_DESTROY_SESSION);
1896fd763d1Szhenwei pi ctrl->header.queue_id = 0;
19059ca6c93Szhenwei pi
1916fd763d1Szhenwei pi destroy_session = &ctrl->u.destroy_session;
19259ca6c93Szhenwei pi destroy_session->session_id = cpu_to_le64(ctx->session_id);
19359ca6c93Szhenwei pi
1946fd763d1Szhenwei pi sg_init_one(&outhdr_sg, ctrl, sizeof(*ctrl));
19559ca6c93Szhenwei pi sgs[num_out++] = &outhdr_sg;
19659ca6c93Szhenwei pi
1976fd763d1Szhenwei pi sg_init_one(&inhdr_sg, &ctrl_status->status, sizeof(ctrl_status->status));
19859ca6c93Szhenwei pi sgs[num_out + num_in++] = &inhdr_sg;
19959ca6c93Szhenwei pi
200977231e8Szhenwei pi err = virtio_crypto_ctrl_vq_request(vcrypto, sgs, num_out, num_in, vc_ctrl_req);
201977231e8Szhenwei pi if (err < 0)
20259ca6c93Szhenwei pi goto out;
20359ca6c93Szhenwei pi
2046fd763d1Szhenwei pi if (ctrl_status->status != VIRTIO_CRYPTO_OK) {
2050756ad15Szhenwei pi pr_err("virtio_crypto: Close session failed status: %u, session_id: 0x%llx\n",
2060756ad15Szhenwei pi ctrl_status->status, destroy_session->session_id);
20759ca6c93Szhenwei pi err = -EINVAL;
20859ca6c93Szhenwei pi goto out;
20959ca6c93Szhenwei pi }
21059ca6c93Szhenwei pi
21159ca6c93Szhenwei pi err = 0;
21259ca6c93Szhenwei pi ctx->session_valid = false;
21359ca6c93Szhenwei pi
21459ca6c93Szhenwei pi out:
2150756ad15Szhenwei pi kfree(vc_ctrl_req);
21659ca6c93Szhenwei pi
21759ca6c93Szhenwei pi return err;
21859ca6c93Szhenwei pi }
21959ca6c93Szhenwei pi
__virtio_crypto_akcipher_do_req(struct virtio_crypto_akcipher_request * vc_akcipher_req,struct akcipher_request * req,struct data_queue * data_vq)22059ca6c93Szhenwei pi static int __virtio_crypto_akcipher_do_req(struct virtio_crypto_akcipher_request *vc_akcipher_req,
22159ca6c93Szhenwei pi struct akcipher_request *req, struct data_queue *data_vq)
22259ca6c93Szhenwei pi {
22359ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *ctx = vc_akcipher_req->akcipher_ctx;
22459ca6c93Szhenwei pi struct virtio_crypto_request *vc_req = &vc_akcipher_req->base;
22559ca6c93Szhenwei pi struct virtio_crypto *vcrypto = ctx->vcrypto;
22659ca6c93Szhenwei pi struct virtio_crypto_op_data_req *req_data = vc_req->req_data;
22759ca6c93Szhenwei pi struct scatterlist *sgs[4], outhdr_sg, inhdr_sg, srcdata_sg, dstdata_sg;
22859ca6c93Szhenwei pi void *src_buf = NULL, *dst_buf = NULL;
22959ca6c93Szhenwei pi unsigned int num_out = 0, num_in = 0;
23059ca6c93Szhenwei pi int node = dev_to_node(&vcrypto->vdev->dev);
23159ca6c93Szhenwei pi unsigned long flags;
23259ca6c93Szhenwei pi int ret = -ENOMEM;
23359ca6c93Szhenwei pi bool verify = vc_akcipher_req->opcode == VIRTIO_CRYPTO_AKCIPHER_VERIFY;
23459ca6c93Szhenwei pi unsigned int src_len = verify ? req->src_len + req->dst_len : req->src_len;
23559ca6c93Szhenwei pi
23659ca6c93Szhenwei pi /* out header */
23759ca6c93Szhenwei pi sg_init_one(&outhdr_sg, req_data, sizeof(*req_data));
23859ca6c93Szhenwei pi sgs[num_out++] = &outhdr_sg;
23959ca6c93Szhenwei pi
24059ca6c93Szhenwei pi /* src data */
24159ca6c93Szhenwei pi src_buf = kcalloc_node(src_len, 1, GFP_KERNEL, node);
24259ca6c93Szhenwei pi if (!src_buf)
24359ca6c93Szhenwei pi goto err;
24459ca6c93Szhenwei pi
24559ca6c93Szhenwei pi if (verify) {
24659ca6c93Szhenwei pi /* for verify operation, both src and dst data work as OUT direction */
24759ca6c93Szhenwei pi sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len);
24859ca6c93Szhenwei pi sg_init_one(&srcdata_sg, src_buf, src_len);
24959ca6c93Szhenwei pi sgs[num_out++] = &srcdata_sg;
25059ca6c93Szhenwei pi } else {
25159ca6c93Szhenwei pi sg_copy_to_buffer(req->src, sg_nents(req->src), src_buf, src_len);
25259ca6c93Szhenwei pi sg_init_one(&srcdata_sg, src_buf, src_len);
25359ca6c93Szhenwei pi sgs[num_out++] = &srcdata_sg;
25459ca6c93Szhenwei pi
25559ca6c93Szhenwei pi /* dst data */
25659ca6c93Szhenwei pi dst_buf = kcalloc_node(req->dst_len, 1, GFP_KERNEL, node);
25759ca6c93Szhenwei pi if (!dst_buf)
25859ca6c93Szhenwei pi goto err;
25959ca6c93Szhenwei pi
26059ca6c93Szhenwei pi sg_init_one(&dstdata_sg, dst_buf, req->dst_len);
26159ca6c93Szhenwei pi sgs[num_out + num_in++] = &dstdata_sg;
26259ca6c93Szhenwei pi }
26359ca6c93Szhenwei pi
26459ca6c93Szhenwei pi vc_akcipher_req->src_buf = src_buf;
26559ca6c93Szhenwei pi vc_akcipher_req->dst_buf = dst_buf;
26659ca6c93Szhenwei pi
26759ca6c93Szhenwei pi /* in header */
26859ca6c93Szhenwei pi sg_init_one(&inhdr_sg, &vc_req->status, sizeof(vc_req->status));
26959ca6c93Szhenwei pi sgs[num_out + num_in++] = &inhdr_sg;
27059ca6c93Szhenwei pi
27159ca6c93Szhenwei pi spin_lock_irqsave(&data_vq->lock, flags);
27259ca6c93Szhenwei pi ret = virtqueue_add_sgs(data_vq->vq, sgs, num_out, num_in, vc_req, GFP_ATOMIC);
27359ca6c93Szhenwei pi virtqueue_kick(data_vq->vq);
27459ca6c93Szhenwei pi spin_unlock_irqrestore(&data_vq->lock, flags);
27559ca6c93Szhenwei pi if (ret)
27659ca6c93Szhenwei pi goto err;
27759ca6c93Szhenwei pi
27859ca6c93Szhenwei pi return 0;
27959ca6c93Szhenwei pi
28059ca6c93Szhenwei pi err:
28159ca6c93Szhenwei pi kfree(src_buf);
28259ca6c93Szhenwei pi kfree(dst_buf);
28359ca6c93Szhenwei pi
28459ca6c93Szhenwei pi return -ENOMEM;
28559ca6c93Szhenwei pi }
28659ca6c93Szhenwei pi
virtio_crypto_rsa_do_req(struct crypto_engine * engine,void * vreq)28759ca6c93Szhenwei pi static int virtio_crypto_rsa_do_req(struct crypto_engine *engine, void *vreq)
28859ca6c93Szhenwei pi {
28959ca6c93Szhenwei pi struct akcipher_request *req = container_of(vreq, struct akcipher_request, base);
29059ca6c93Szhenwei pi struct virtio_crypto_akcipher_request *vc_akcipher_req = akcipher_request_ctx(req);
29159ca6c93Szhenwei pi struct virtio_crypto_request *vc_req = &vc_akcipher_req->base;
29259ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *ctx = vc_akcipher_req->akcipher_ctx;
29359ca6c93Szhenwei pi struct virtio_crypto *vcrypto = ctx->vcrypto;
29459ca6c93Szhenwei pi struct data_queue *data_vq = vc_req->dataq;
29559ca6c93Szhenwei pi struct virtio_crypto_op_header *header;
29659ca6c93Szhenwei pi struct virtio_crypto_akcipher_data_req *akcipher_req;
29759ca6c93Szhenwei pi int ret;
29859ca6c93Szhenwei pi
29959ca6c93Szhenwei pi vc_req->sgs = NULL;
30059ca6c93Szhenwei pi vc_req->req_data = kzalloc_node(sizeof(*vc_req->req_data),
30159ca6c93Szhenwei pi GFP_KERNEL, dev_to_node(&vcrypto->vdev->dev));
30259ca6c93Szhenwei pi if (!vc_req->req_data)
30359ca6c93Szhenwei pi return -ENOMEM;
30459ca6c93Szhenwei pi
30559ca6c93Szhenwei pi /* build request header */
30659ca6c93Szhenwei pi header = &vc_req->req_data->header;
30759ca6c93Szhenwei pi header->opcode = cpu_to_le32(vc_akcipher_req->opcode);
30859ca6c93Szhenwei pi header->algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_RSA);
30959ca6c93Szhenwei pi header->session_id = cpu_to_le64(ctx->session_id);
31059ca6c93Szhenwei pi
31159ca6c93Szhenwei pi /* build request akcipher data */
31259ca6c93Szhenwei pi akcipher_req = &vc_req->req_data->u.akcipher_req;
31359ca6c93Szhenwei pi akcipher_req->para.src_data_len = cpu_to_le32(req->src_len);
31459ca6c93Szhenwei pi akcipher_req->para.dst_data_len = cpu_to_le32(req->dst_len);
31559ca6c93Szhenwei pi
31659ca6c93Szhenwei pi ret = __virtio_crypto_akcipher_do_req(vc_akcipher_req, req, data_vq);
31759ca6c93Szhenwei pi if (ret < 0) {
31859ca6c93Szhenwei pi kfree_sensitive(vc_req->req_data);
31959ca6c93Szhenwei pi vc_req->req_data = NULL;
32059ca6c93Szhenwei pi return ret;
32159ca6c93Szhenwei pi }
32259ca6c93Szhenwei pi
32359ca6c93Szhenwei pi return 0;
32459ca6c93Szhenwei pi }
32559ca6c93Szhenwei pi
virtio_crypto_rsa_req(struct akcipher_request * req,uint32_t opcode)32659ca6c93Szhenwei pi static int virtio_crypto_rsa_req(struct akcipher_request *req, uint32_t opcode)
32759ca6c93Szhenwei pi {
32859ca6c93Szhenwei pi struct crypto_akcipher *atfm = crypto_akcipher_reqtfm(req);
32959ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(atfm);
33059ca6c93Szhenwei pi struct virtio_crypto_akcipher_request *vc_akcipher_req = akcipher_request_ctx(req);
33159ca6c93Szhenwei pi struct virtio_crypto_request *vc_req = &vc_akcipher_req->base;
33259ca6c93Szhenwei pi struct virtio_crypto *vcrypto = ctx->vcrypto;
33359ca6c93Szhenwei pi /* Use the first data virtqueue as default */
33459ca6c93Szhenwei pi struct data_queue *data_vq = &vcrypto->data_vq[0];
33559ca6c93Szhenwei pi
33659ca6c93Szhenwei pi vc_req->dataq = data_vq;
33759ca6c93Szhenwei pi vc_req->alg_cb = virtio_crypto_dataq_akcipher_callback;
33859ca6c93Szhenwei pi vc_akcipher_req->akcipher_ctx = ctx;
33959ca6c93Szhenwei pi vc_akcipher_req->akcipher_req = req;
34059ca6c93Szhenwei pi vc_akcipher_req->opcode = opcode;
34159ca6c93Szhenwei pi
34259ca6c93Szhenwei pi return crypto_transfer_akcipher_request_to_engine(data_vq->engine, req);
34359ca6c93Szhenwei pi }
34459ca6c93Szhenwei pi
virtio_crypto_rsa_encrypt(struct akcipher_request * req)34559ca6c93Szhenwei pi static int virtio_crypto_rsa_encrypt(struct akcipher_request *req)
34659ca6c93Szhenwei pi {
34759ca6c93Szhenwei pi return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_ENCRYPT);
34859ca6c93Szhenwei pi }
34959ca6c93Szhenwei pi
virtio_crypto_rsa_decrypt(struct akcipher_request * req)35059ca6c93Szhenwei pi static int virtio_crypto_rsa_decrypt(struct akcipher_request *req)
35159ca6c93Szhenwei pi {
35259ca6c93Szhenwei pi return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_DECRYPT);
35359ca6c93Szhenwei pi }
35459ca6c93Szhenwei pi
virtio_crypto_rsa_sign(struct akcipher_request * req)35559ca6c93Szhenwei pi static int virtio_crypto_rsa_sign(struct akcipher_request *req)
35659ca6c93Szhenwei pi {
35759ca6c93Szhenwei pi return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_SIGN);
35859ca6c93Szhenwei pi }
35959ca6c93Szhenwei pi
virtio_crypto_rsa_verify(struct akcipher_request * req)36059ca6c93Szhenwei pi static int virtio_crypto_rsa_verify(struct akcipher_request *req)
36159ca6c93Szhenwei pi {
36259ca6c93Szhenwei pi return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_VERIFY);
36359ca6c93Szhenwei pi }
36459ca6c93Szhenwei pi
virtio_crypto_rsa_set_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen,bool private,int padding_algo,int hash_algo)36559ca6c93Szhenwei pi static int virtio_crypto_rsa_set_key(struct crypto_akcipher *tfm,
36659ca6c93Szhenwei pi const void *key,
36759ca6c93Szhenwei pi unsigned int keylen,
36859ca6c93Szhenwei pi bool private,
36959ca6c93Szhenwei pi int padding_algo,
37059ca6c93Szhenwei pi int hash_algo)
37159ca6c93Szhenwei pi {
37259ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
37359ca6c93Szhenwei pi struct virtio_crypto_rsa_ctx *rsa_ctx = &ctx->rsa_ctx;
37459ca6c93Szhenwei pi struct virtio_crypto *vcrypto;
37559ca6c93Szhenwei pi struct virtio_crypto_ctrl_header header;
37659ca6c93Szhenwei pi struct virtio_crypto_akcipher_session_para para;
37759ca6c93Szhenwei pi struct rsa_key rsa_key = {0};
37859ca6c93Szhenwei pi int node = virtio_crypto_get_current_node();
37959ca6c93Szhenwei pi uint32_t keytype;
38059ca6c93Szhenwei pi int ret;
38159ca6c93Szhenwei pi
38259ca6c93Szhenwei pi /* mpi_free will test n, just free it. */
38359ca6c93Szhenwei pi mpi_free(rsa_ctx->n);
38459ca6c93Szhenwei pi rsa_ctx->n = NULL;
38559ca6c93Szhenwei pi
38659ca6c93Szhenwei pi if (private) {
38759ca6c93Szhenwei pi keytype = VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE;
38859ca6c93Szhenwei pi ret = rsa_parse_priv_key(&rsa_key, key, keylen);
38959ca6c93Szhenwei pi } else {
39059ca6c93Szhenwei pi keytype = VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC;
39159ca6c93Szhenwei pi ret = rsa_parse_pub_key(&rsa_key, key, keylen);
39259ca6c93Szhenwei pi }
39359ca6c93Szhenwei pi
39459ca6c93Szhenwei pi if (ret)
39559ca6c93Szhenwei pi return ret;
39659ca6c93Szhenwei pi
39759ca6c93Szhenwei pi rsa_ctx->n = mpi_read_raw_data(rsa_key.n, rsa_key.n_sz);
39859ca6c93Szhenwei pi if (!rsa_ctx->n)
39959ca6c93Szhenwei pi return -ENOMEM;
40059ca6c93Szhenwei pi
40159ca6c93Szhenwei pi if (!ctx->vcrypto) {
40259ca6c93Szhenwei pi vcrypto = virtcrypto_get_dev_node(node, VIRTIO_CRYPTO_SERVICE_AKCIPHER,
40359ca6c93Szhenwei pi VIRTIO_CRYPTO_AKCIPHER_RSA);
40459ca6c93Szhenwei pi if (!vcrypto) {
40559ca6c93Szhenwei pi pr_err("virtio_crypto: Could not find a virtio device in the system or unsupported algo\n");
40659ca6c93Szhenwei pi return -ENODEV;
40759ca6c93Szhenwei pi }
40859ca6c93Szhenwei pi
40959ca6c93Szhenwei pi ctx->vcrypto = vcrypto;
41059ca6c93Szhenwei pi } else {
41159ca6c93Szhenwei pi virtio_crypto_alg_akcipher_close_session(ctx);
41259ca6c93Szhenwei pi }
41359ca6c93Szhenwei pi
41459ca6c93Szhenwei pi /* set ctrl header */
41559ca6c93Szhenwei pi header.opcode = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION);
41659ca6c93Szhenwei pi header.algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_RSA);
41759ca6c93Szhenwei pi header.queue_id = 0;
41859ca6c93Szhenwei pi
41959ca6c93Szhenwei pi /* set RSA para */
42059ca6c93Szhenwei pi para.algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_RSA);
42159ca6c93Szhenwei pi para.keytype = cpu_to_le32(keytype);
42259ca6c93Szhenwei pi para.keylen = cpu_to_le32(keylen);
42359ca6c93Szhenwei pi para.u.rsa.padding_algo = cpu_to_le32(padding_algo);
42459ca6c93Szhenwei pi para.u.rsa.hash_algo = cpu_to_le32(hash_algo);
42559ca6c93Szhenwei pi
42659ca6c93Szhenwei pi return virtio_crypto_alg_akcipher_init_session(ctx, &header, ¶, key, keylen);
42759ca6c93Szhenwei pi }
42859ca6c93Szhenwei pi
virtio_crypto_rsa_raw_set_priv_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)42959ca6c93Szhenwei pi static int virtio_crypto_rsa_raw_set_priv_key(struct crypto_akcipher *tfm,
43059ca6c93Szhenwei pi const void *key,
43159ca6c93Szhenwei pi unsigned int keylen)
43259ca6c93Szhenwei pi {
43359ca6c93Szhenwei pi return virtio_crypto_rsa_set_key(tfm, key, keylen, 1,
43459ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_RAW_PADDING,
43559ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_NO_HASH);
43659ca6c93Szhenwei pi }
43759ca6c93Szhenwei pi
43859ca6c93Szhenwei pi
virtio_crypto_p1pad_rsa_sha1_set_priv_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)43959ca6c93Szhenwei pi static int virtio_crypto_p1pad_rsa_sha1_set_priv_key(struct crypto_akcipher *tfm,
44059ca6c93Szhenwei pi const void *key,
44159ca6c93Szhenwei pi unsigned int keylen)
44259ca6c93Szhenwei pi {
44359ca6c93Szhenwei pi return virtio_crypto_rsa_set_key(tfm, key, keylen, 1,
44459ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_PKCS1_PADDING,
44559ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_SHA1);
44659ca6c93Szhenwei pi }
44759ca6c93Szhenwei pi
virtio_crypto_rsa_raw_set_pub_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)44859ca6c93Szhenwei pi static int virtio_crypto_rsa_raw_set_pub_key(struct crypto_akcipher *tfm,
44959ca6c93Szhenwei pi const void *key,
45059ca6c93Szhenwei pi unsigned int keylen)
45159ca6c93Szhenwei pi {
45259ca6c93Szhenwei pi return virtio_crypto_rsa_set_key(tfm, key, keylen, 0,
45359ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_RAW_PADDING,
45459ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_NO_HASH);
45559ca6c93Szhenwei pi }
45659ca6c93Szhenwei pi
virtio_crypto_p1pad_rsa_sha1_set_pub_key(struct crypto_akcipher * tfm,const void * key,unsigned int keylen)45759ca6c93Szhenwei pi static int virtio_crypto_p1pad_rsa_sha1_set_pub_key(struct crypto_akcipher *tfm,
45859ca6c93Szhenwei pi const void *key,
45959ca6c93Szhenwei pi unsigned int keylen)
46059ca6c93Szhenwei pi {
46159ca6c93Szhenwei pi return virtio_crypto_rsa_set_key(tfm, key, keylen, 0,
46259ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_PKCS1_PADDING,
46359ca6c93Szhenwei pi VIRTIO_CRYPTO_RSA_SHA1);
46459ca6c93Szhenwei pi }
46559ca6c93Szhenwei pi
virtio_crypto_rsa_max_size(struct crypto_akcipher * tfm)46659ca6c93Szhenwei pi static unsigned int virtio_crypto_rsa_max_size(struct crypto_akcipher *tfm)
46759ca6c93Szhenwei pi {
46859ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
46959ca6c93Szhenwei pi struct virtio_crypto_rsa_ctx *rsa_ctx = &ctx->rsa_ctx;
47059ca6c93Szhenwei pi
47159ca6c93Szhenwei pi return mpi_get_size(rsa_ctx->n);
47259ca6c93Szhenwei pi }
47359ca6c93Szhenwei pi
virtio_crypto_rsa_init_tfm(struct crypto_akcipher * tfm)47459ca6c93Szhenwei pi static int virtio_crypto_rsa_init_tfm(struct crypto_akcipher *tfm)
47559ca6c93Szhenwei pi {
47659ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
47759ca6c93Szhenwei pi
47859ca6c93Szhenwei pi ctx->tfm = tfm;
47959ca6c93Szhenwei pi
48093c446cdSHerbert Xu akcipher_set_reqsize(tfm,
48193c446cdSHerbert Xu sizeof(struct virtio_crypto_akcipher_request));
48293c446cdSHerbert Xu
48359ca6c93Szhenwei pi return 0;
48459ca6c93Szhenwei pi }
48559ca6c93Szhenwei pi
virtio_crypto_rsa_exit_tfm(struct crypto_akcipher * tfm)48659ca6c93Szhenwei pi static void virtio_crypto_rsa_exit_tfm(struct crypto_akcipher *tfm)
48759ca6c93Szhenwei pi {
48859ca6c93Szhenwei pi struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
48959ca6c93Szhenwei pi struct virtio_crypto_rsa_ctx *rsa_ctx = &ctx->rsa_ctx;
49059ca6c93Szhenwei pi
49159ca6c93Szhenwei pi virtio_crypto_alg_akcipher_close_session(ctx);
49259ca6c93Szhenwei pi virtcrypto_dev_put(ctx->vcrypto);
49359ca6c93Szhenwei pi mpi_free(rsa_ctx->n);
49459ca6c93Szhenwei pi rsa_ctx->n = NULL;
49559ca6c93Szhenwei pi }
49659ca6c93Szhenwei pi
49759ca6c93Szhenwei pi static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = {
49859ca6c93Szhenwei pi {
49959ca6c93Szhenwei pi .algonum = VIRTIO_CRYPTO_AKCIPHER_RSA,
50059ca6c93Szhenwei pi .service = VIRTIO_CRYPTO_SERVICE_AKCIPHER,
5017a2673d7SHerbert Xu .algo.base = {
50259ca6c93Szhenwei pi .encrypt = virtio_crypto_rsa_encrypt,
50359ca6c93Szhenwei pi .decrypt = virtio_crypto_rsa_decrypt,
50459ca6c93Szhenwei pi .set_pub_key = virtio_crypto_rsa_raw_set_pub_key,
50559ca6c93Szhenwei pi .set_priv_key = virtio_crypto_rsa_raw_set_priv_key,
50659ca6c93Szhenwei pi .max_size = virtio_crypto_rsa_max_size,
50759ca6c93Szhenwei pi .init = virtio_crypto_rsa_init_tfm,
50859ca6c93Szhenwei pi .exit = virtio_crypto_rsa_exit_tfm,
50959ca6c93Szhenwei pi .base = {
51059ca6c93Szhenwei pi .cra_name = "rsa",
51159ca6c93Szhenwei pi .cra_driver_name = "virtio-crypto-rsa",
51259ca6c93Szhenwei pi .cra_priority = 150,
51359ca6c93Szhenwei pi .cra_module = THIS_MODULE,
51459ca6c93Szhenwei pi .cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx),
51559ca6c93Szhenwei pi },
51659ca6c93Szhenwei pi },
5177a2673d7SHerbert Xu .algo.op = {
5187a2673d7SHerbert Xu .do_one_request = virtio_crypto_rsa_do_req,
5197a2673d7SHerbert Xu },
52059ca6c93Szhenwei pi },
52159ca6c93Szhenwei pi {
52259ca6c93Szhenwei pi .algonum = VIRTIO_CRYPTO_AKCIPHER_RSA,
52359ca6c93Szhenwei pi .service = VIRTIO_CRYPTO_SERVICE_AKCIPHER,
5247a2673d7SHerbert Xu .algo.base = {
52559ca6c93Szhenwei pi .encrypt = virtio_crypto_rsa_encrypt,
52659ca6c93Szhenwei pi .decrypt = virtio_crypto_rsa_decrypt,
52759ca6c93Szhenwei pi .sign = virtio_crypto_rsa_sign,
52859ca6c93Szhenwei pi .verify = virtio_crypto_rsa_verify,
52959ca6c93Szhenwei pi .set_pub_key = virtio_crypto_p1pad_rsa_sha1_set_pub_key,
53059ca6c93Szhenwei pi .set_priv_key = virtio_crypto_p1pad_rsa_sha1_set_priv_key,
53159ca6c93Szhenwei pi .max_size = virtio_crypto_rsa_max_size,
53259ca6c93Szhenwei pi .init = virtio_crypto_rsa_init_tfm,
53359ca6c93Szhenwei pi .exit = virtio_crypto_rsa_exit_tfm,
53459ca6c93Szhenwei pi .base = {
53559ca6c93Szhenwei pi .cra_name = "pkcs1pad(rsa,sha1)",
53659ca6c93Szhenwei pi .cra_driver_name = "virtio-pkcs1-rsa-with-sha1",
53759ca6c93Szhenwei pi .cra_priority = 150,
53859ca6c93Szhenwei pi .cra_module = THIS_MODULE,
53959ca6c93Szhenwei pi .cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx),
54059ca6c93Szhenwei pi },
54159ca6c93Szhenwei pi },
5427a2673d7SHerbert Xu .algo.op = {
5437a2673d7SHerbert Xu .do_one_request = virtio_crypto_rsa_do_req,
5447a2673d7SHerbert Xu },
54559ca6c93Szhenwei pi },
54659ca6c93Szhenwei pi };
54759ca6c93Szhenwei pi
virtio_crypto_akcipher_algs_register(struct virtio_crypto * vcrypto)54859ca6c93Szhenwei pi int virtio_crypto_akcipher_algs_register(struct virtio_crypto *vcrypto)
54959ca6c93Szhenwei pi {
55059ca6c93Szhenwei pi int ret = 0;
55159ca6c93Szhenwei pi int i = 0;
55259ca6c93Szhenwei pi
55359ca6c93Szhenwei pi mutex_lock(&algs_lock);
55459ca6c93Szhenwei pi
55559ca6c93Szhenwei pi for (i = 0; i < ARRAY_SIZE(virtio_crypto_akcipher_algs); i++) {
55659ca6c93Szhenwei pi uint32_t service = virtio_crypto_akcipher_algs[i].service;
55759ca6c93Szhenwei pi uint32_t algonum = virtio_crypto_akcipher_algs[i].algonum;
55859ca6c93Szhenwei pi
55959ca6c93Szhenwei pi if (!virtcrypto_algo_is_supported(vcrypto, service, algonum))
56059ca6c93Szhenwei pi continue;
56159ca6c93Szhenwei pi
56259ca6c93Szhenwei pi if (virtio_crypto_akcipher_algs[i].active_devs == 0) {
5637a2673d7SHerbert Xu ret = crypto_engine_register_akcipher(&virtio_crypto_akcipher_algs[i].algo);
56459ca6c93Szhenwei pi if (ret)
56559ca6c93Szhenwei pi goto unlock;
56659ca6c93Szhenwei pi }
56759ca6c93Szhenwei pi
56859ca6c93Szhenwei pi virtio_crypto_akcipher_algs[i].active_devs++;
56959ca6c93Szhenwei pi dev_info(&vcrypto->vdev->dev, "Registered akcipher algo %s\n",
5707a2673d7SHerbert Xu virtio_crypto_akcipher_algs[i].algo.base.base.cra_name);
57159ca6c93Szhenwei pi }
57259ca6c93Szhenwei pi
57359ca6c93Szhenwei pi unlock:
57459ca6c93Szhenwei pi mutex_unlock(&algs_lock);
57559ca6c93Szhenwei pi return ret;
57659ca6c93Szhenwei pi }
57759ca6c93Szhenwei pi
virtio_crypto_akcipher_algs_unregister(struct virtio_crypto * vcrypto)57859ca6c93Szhenwei pi void virtio_crypto_akcipher_algs_unregister(struct virtio_crypto *vcrypto)
57959ca6c93Szhenwei pi {
58059ca6c93Szhenwei pi int i = 0;
58159ca6c93Szhenwei pi
58259ca6c93Szhenwei pi mutex_lock(&algs_lock);
58359ca6c93Szhenwei pi
58459ca6c93Szhenwei pi for (i = 0; i < ARRAY_SIZE(virtio_crypto_akcipher_algs); i++) {
58559ca6c93Szhenwei pi uint32_t service = virtio_crypto_akcipher_algs[i].service;
58659ca6c93Szhenwei pi uint32_t algonum = virtio_crypto_akcipher_algs[i].algonum;
58759ca6c93Szhenwei pi
58859ca6c93Szhenwei pi if (virtio_crypto_akcipher_algs[i].active_devs == 0 ||
58959ca6c93Szhenwei pi !virtcrypto_algo_is_supported(vcrypto, service, algonum))
59059ca6c93Szhenwei pi continue;
59159ca6c93Szhenwei pi
59259ca6c93Szhenwei pi if (virtio_crypto_akcipher_algs[i].active_devs == 1)
5937a2673d7SHerbert Xu crypto_engine_unregister_akcipher(&virtio_crypto_akcipher_algs[i].algo);
59459ca6c93Szhenwei pi
59559ca6c93Szhenwei pi virtio_crypto_akcipher_algs[i].active_devs--;
59659ca6c93Szhenwei pi }
59759ca6c93Szhenwei pi
59859ca6c93Szhenwei pi mutex_unlock(&algs_lock);
59959ca6c93Szhenwei pi }
600