linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lei He <helei.sig11@bytedance.com>
To: davem@davemloft.net, herbert@gondor.apana.org.au, dhowells@redhat.com
Cc: mst@redhat.com, linux-crypto@vger.kernel.org,
	linux-kernel@vger.kernel.org, berrange@redhat.com,
	pizhenwei@bytedance.com, lei he <helei.sig11@bytedance.com>
Subject: [PATCH v2 4/4] virtio-crypto: support ECDSA algorithm
Date: Thu, 23 Jun 2022 15:05:50 +0800	[thread overview]
Message-ID: <20220623070550.82053-5-helei.sig11@bytedance.com> (raw)
In-Reply-To: <20220623070550.82053-1-helei.sig11@bytedance.com>

From: lei he <helei.sig11@bytedance.com>

Support ECDSA algorithm for driver virtio-crypto

Signed-off-by: lei he <helei.sig11@bytedance.com>
---
 drivers/crypto/virtio/Kconfig                 |   1 +
 .../virtio/virtio_crypto_akcipher_algs.c      | 259 ++++++++++++++++--
 2 files changed, 239 insertions(+), 21 deletions(-)

diff --git a/drivers/crypto/virtio/Kconfig b/drivers/crypto/virtio/Kconfig
index 5f8915f4a9ff..c4b66cf17d7c 100644
--- a/drivers/crypto/virtio/Kconfig
+++ b/drivers/crypto/virtio/Kconfig
@@ -6,6 +6,7 @@ config CRYPTO_DEV_VIRTIO
 	select CRYPTO_AKCIPHER2
 	select CRYPTO_SKCIPHER
 	select CRYPTO_ENGINE
+	select CRYPTO_ECDSA
 	select CRYPTO_RSA
 	select MPILIB
 	help
diff --git a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
index 2a60d0525cde..da628a6de696 100644
--- a/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
+++ b/drivers/crypto/virtio/virtio_crypto_akcipher_algs.c
@@ -10,7 +10,9 @@
 #include <linux/mpi.h>
 #include <linux/scatterlist.h>
 #include <crypto/algapi.h>
+#include <crypto/ecdh.h>
 #include <crypto/internal/akcipher.h>
+#include <crypto/internal/ecdsa.h>
 #include <crypto/internal/rsa.h>
 #include <linux/err.h>
 #include <crypto/scatterwalk.h>
@@ -23,6 +25,10 @@ struct virtio_crypto_rsa_ctx {
 	MPI n;
 };
 
+struct virtio_crypto_ecdsa_ctx {
+	const struct ecc_curve *curve;
+};
+
 struct virtio_crypto_akcipher_ctx {
 	struct crypto_engine_ctx enginectx;
 	struct virtio_crypto *vcrypto;
@@ -31,6 +37,7 @@ struct virtio_crypto_akcipher_ctx {
 	__u64 session_id;
 	union {
 		struct virtio_crypto_rsa_ctx rsa_ctx;
+		struct virtio_crypto_ecdsa_ctx ecdsa_ctx;
 	};
 };
 
@@ -279,7 +286,7 @@ static int __virtio_crypto_akcipher_do_req(struct virtio_crypto_akcipher_request
 	return -ENOMEM;
 }
 
-static int virtio_crypto_rsa_do_req(struct crypto_engine *engine, void *vreq)
+static int virtio_crypto_akcipher_do_req(struct crypto_engine *engine, void *vreq, int algo)
 {
 	struct akcipher_request *req = container_of(vreq, struct akcipher_request, base);
 	struct virtio_crypto_akcipher_request *vc_akcipher_req = akcipher_request_ctx(req);
@@ -300,7 +307,7 @@ static int virtio_crypto_rsa_do_req(struct crypto_engine *engine, void *vreq)
 	/* build request header */
 	header = &vc_req->req_data->header;
 	header->opcode = cpu_to_le32(vc_akcipher_req->opcode);
-	header->algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_RSA);
+	header->algo = cpu_to_le32(algo);
 	header->session_id = cpu_to_le64(ctx->session_id);
 
 	/* build request akcipher data */
@@ -318,7 +325,12 @@ static int virtio_crypto_rsa_do_req(struct crypto_engine *engine, void *vreq)
 	return 0;
 }
 
-static int virtio_crypto_rsa_req(struct akcipher_request *req, uint32_t opcode)
+static int virtio_crypto_rsa_do_req(struct crypto_engine *engine, void *vreq)
+{
+	return virtio_crypto_akcipher_do_req(engine, vreq, VIRTIO_CRYPTO_AKCIPHER_RSA);
+}
+
+static int virtio_crypto_akcipher_req(struct akcipher_request *req, uint32_t opcode)
 {
 	struct crypto_akcipher *atfm = crypto_akcipher_reqtfm(req);
 	struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(atfm);
@@ -337,24 +349,24 @@ static int virtio_crypto_rsa_req(struct akcipher_request *req, uint32_t opcode)
 	return crypto_transfer_akcipher_request_to_engine(data_vq->engine, req);
 }
 
-static int virtio_crypto_rsa_encrypt(struct akcipher_request *req)
+static int virtio_crypto_akcipher_encrypt(struct akcipher_request *req)
 {
-	return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_ENCRYPT);
+	return virtio_crypto_akcipher_req(req, VIRTIO_CRYPTO_AKCIPHER_ENCRYPT);
 }
 
-static int virtio_crypto_rsa_decrypt(struct akcipher_request *req)
+static int virtio_crypto_akcipher_decrypt(struct akcipher_request *req)
 {
-	return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_DECRYPT);
+	return virtio_crypto_akcipher_req(req, VIRTIO_CRYPTO_AKCIPHER_DECRYPT);
 }
 
-static int virtio_crypto_rsa_sign(struct akcipher_request *req)
+static int virtio_crypto_akcipher_sign(struct akcipher_request *req)
 {
-	return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_SIGN);
+	return virtio_crypto_akcipher_req(req, VIRTIO_CRYPTO_AKCIPHER_SIGN);
 }
 
-static int virtio_crypto_rsa_verify(struct akcipher_request *req)
+static int virtio_crypto_akcipher_verify(struct akcipher_request *req)
 {
-	return virtio_crypto_rsa_req(req, VIRTIO_CRYPTO_AKCIPHER_VERIFY);
+	return virtio_crypto_akcipher_req(req, VIRTIO_CRYPTO_AKCIPHER_VERIFY);
 }
 
 static int virtio_crypto_rsa_set_key(struct crypto_akcipher *tfm,
@@ -484,18 +496,161 @@ static void virtio_crypto_rsa_exit_tfm(struct crypto_akcipher *tfm)
 	struct virtio_crypto_rsa_ctx *rsa_ctx = &ctx->rsa_ctx;
 
 	virtio_crypto_alg_akcipher_close_session(ctx);
-	virtcrypto_dev_put(ctx->vcrypto);
+	if (ctx->vcrypto)
+		virtcrypto_dev_put(ctx->vcrypto);
 	mpi_free(rsa_ctx->n);
 	rsa_ctx->n = NULL;
 }
 
+static int virtio_crypto_ecdsa_do_req(struct crypto_engine *engine, void *vreq)
+{
+	return virtio_crypto_akcipher_do_req(engine, vreq, VIRTIO_CRYPTO_AKCIPHER_ECDSA);
+}
+
+static int virtio_crypto_ecdsa_set_key(struct crypto_akcipher *tfm,
+				       const void *key,
+				       unsigned int keylen,
+				       bool private,
+				       int curve_id)
+{
+	struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct virtio_crypto *vcrypto;
+	struct virtio_crypto_ctrl_header header;
+	struct virtio_crypto_akcipher_session_para para;
+	int node = virtio_crypto_get_current_node();
+	uint32_t keytype;
+
+	if (private)
+		keytype = VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PRIVATE;
+	else
+		keytype = VIRTIO_CRYPTO_AKCIPHER_KEY_TYPE_PUBLIC;
+
+	if (!ctx->vcrypto) {
+		vcrypto = virtcrypto_get_dev_node(node, VIRTIO_CRYPTO_SERVICE_AKCIPHER,
+						VIRTIO_CRYPTO_AKCIPHER_RSA);
+		if (!vcrypto) {
+			pr_err("virtio_crypto: Could not find a virtio device in the system or unsupported algo\n");
+			return -ENODEV;
+		}
+
+		ctx->vcrypto = vcrypto;
+	} else {
+		virtio_crypto_alg_akcipher_close_session(ctx);
+	}
+
+	/* set ctrl header */
+	header.opcode =	cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_CREATE_SESSION);
+	header.algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_ECDSA);
+	header.queue_id = 0;
+
+	/* set ECDSA para */
+	para.algo = cpu_to_le32(VIRTIO_CRYPTO_AKCIPHER_ECDSA);
+	para.keytype = cpu_to_le32(keytype);
+	para.keylen = cpu_to_le32(keylen);
+	para.u.ecdsa.curve_id = cpu_to_le32(curve_id);
+
+	return virtio_crypto_alg_akcipher_init_session(ctx, &header, &para, key, keylen);
+}
+
+static int virtio_crypto_ecdsa_nist_p192_set_pub_key(struct crypto_akcipher *tfm,
+						     const void *key,
+						     unsigned int keylen)
+{
+	return virtio_crypto_ecdsa_set_key(tfm, key, keylen, 0, VIRTIO_CRYPTO_CURVE_NIST_P192);
+}
+
+static int virtio_crypto_ecdsa_nist_p192_set_priv_key(struct crypto_akcipher *tfm,
+						      const void *key,
+						      unsigned int keylen)
+{
+	return virtio_crypto_ecdsa_set_key(tfm, key, keylen, 1, VIRTIO_CRYPTO_CURVE_NIST_P192);
+}
+
+static int virtio_crypto_ecdsa_nist_p256_set_pub_key(struct crypto_akcipher *tfm,
+						     const void *key,
+						     unsigned int keylen)
+{
+	return virtio_crypto_ecdsa_set_key(tfm, key, keylen, 0, VIRTIO_CRYPTO_CURVE_NIST_P256);
+}
+
+static int virtio_crypto_ecdsa_nist_p256_set_priv_key(struct crypto_akcipher *tfm,
+						      const void *key,
+						      unsigned int keylen)
+{
+	return virtio_crypto_ecdsa_set_key(tfm, key, keylen, 1, VIRTIO_CRYPTO_CURVE_NIST_P256);
+}
+
+static int virtio_crypto_ecdsa_nist_p384_set_pub_key(struct crypto_akcipher *tfm,
+						     const void *key,
+						     unsigned int keylen)
+{
+	return virtio_crypto_ecdsa_set_key(tfm, key, keylen, 0, VIRTIO_CRYPTO_CURVE_NIST_P384);
+}
+
+static int virtio_crypto_ecdsa_nist_p384_set_priv_key(struct crypto_akcipher *tfm,
+						      const void *key,
+						      unsigned int keylen)
+{
+	return virtio_crypto_ecdsa_set_key(tfm, key, keylen, 1, VIRTIO_CRYPTO_CURVE_NIST_P384);
+}
+
+static unsigned int virtio_crypto_ecdsa_max_size(struct crypto_akcipher *tfm)
+{
+	struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct virtio_crypto_ecdsa_ctx *ecdsa_ctx = &ctx->ecdsa_ctx;
+
+	return ecdsa_max_signature_size(ecdsa_ctx->curve);
+}
+
+static int virtio_crypto_ecdsa_init_tfm(struct crypto_akcipher *tfm, unsigned int curve_id)
+{
+	struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
+
+	ctx->tfm = tfm;
+	ctx->enginectx.op.do_one_request = virtio_crypto_ecdsa_do_req;
+	ctx->enginectx.op.prepare_request = NULL;
+	ctx->enginectx.op.unprepare_request = NULL;
+	ctx->ecdsa_ctx.curve = ecc_get_curve(curve_id);
+
+	if (!ctx->ecdsa_ctx.curve)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int virtio_crypto_ecdsa_nist_p192_init_tfm(struct crypto_akcipher *tfm)
+{
+	return virtio_crypto_ecdsa_init_tfm(tfm, ECC_CURVE_NIST_P192);
+}
+
+static int virtio_crypto_ecdsa_nist_p256_init_tfm(struct crypto_akcipher *tfm)
+{
+	return virtio_crypto_ecdsa_init_tfm(tfm, ECC_CURVE_NIST_P256);
+}
+
+static int virtio_crypto_ecdsa_nist_p384_init_tfm(struct crypto_akcipher *tfm)
+{
+	return virtio_crypto_ecdsa_init_tfm(tfm, ECC_CURVE_NIST_P384);
+}
+
+static void virtio_crypto_ecdsa_exit_tfm(struct crypto_akcipher *tfm)
+{
+	struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
+	struct virtio_crypto_ecdsa_ctx *ecdsa_ctx = &ctx->ecdsa_ctx;
+
+	virtio_crypto_alg_akcipher_close_session(ctx);
+	ecdsa_ctx->curve = NULL;
+	if (ctx->vcrypto)
+		virtcrypto_dev_put(ctx->vcrypto);
+}
+
 static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = {
 	{
 		.algonum = VIRTIO_CRYPTO_AKCIPHER_RSA,
 		.service = VIRTIO_CRYPTO_SERVICE_AKCIPHER,
 		.algo = {
-			.encrypt = virtio_crypto_rsa_encrypt,
-			.decrypt = virtio_crypto_rsa_decrypt,
+			.encrypt = virtio_crypto_akcipher_encrypt,
+			.decrypt = virtio_crypto_akcipher_decrypt,
 			.set_pub_key = virtio_crypto_rsa_raw_set_pub_key,
 			.set_priv_key = virtio_crypto_rsa_raw_set_priv_key,
 			.max_size = virtio_crypto_rsa_max_size,
@@ -515,10 +670,10 @@ static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = {
 		.algonum = VIRTIO_CRYPTO_AKCIPHER_RSA,
 		.service = VIRTIO_CRYPTO_SERVICE_AKCIPHER,
 		.algo = {
-			.encrypt = virtio_crypto_rsa_encrypt,
-			.decrypt = virtio_crypto_rsa_decrypt,
-			.sign = virtio_crypto_rsa_sign,
-			.verify = virtio_crypto_rsa_verify,
+			.encrypt = virtio_crypto_akcipher_encrypt,
+			.decrypt = virtio_crypto_akcipher_decrypt,
+			.sign = virtio_crypto_akcipher_sign,
+			.verify = virtio_crypto_akcipher_verify,
 			.set_pub_key = virtio_crypto_p1pad_rsa_sha1_set_pub_key,
 			.set_priv_key = virtio_crypto_p1pad_rsa_sha1_set_priv_key,
 			.max_size = virtio_crypto_rsa_max_size,
@@ -534,6 +689,70 @@ static struct virtio_crypto_akcipher_algo virtio_crypto_akcipher_algs[] = {
 			},
 		},
 	},
+	{
+		.algonum = VIRTIO_CRYPTO_AKCIPHER_ECDSA,
+		.service = VIRTIO_CRYPTO_SERVICE_AKCIPHER,
+		.algo = {
+			.sign = virtio_crypto_akcipher_sign,
+			.verify = virtio_crypto_akcipher_verify,
+			.set_pub_key = virtio_crypto_ecdsa_nist_p192_set_pub_key,
+			.set_priv_key = virtio_crypto_ecdsa_nist_p192_set_priv_key,
+			.max_size = virtio_crypto_ecdsa_max_size,
+			.init = virtio_crypto_ecdsa_nist_p192_init_tfm,
+			.exit = virtio_crypto_ecdsa_exit_tfm,
+			.reqsize = sizeof(struct virtio_crypto_akcipher_request),
+			.base = {
+				.cra_name = "ecdsa-nist-p192",
+				.cra_driver_name = "virtio-ecdsa-nist-p192",
+				.cra_priority = 150,
+				.cra_module = THIS_MODULE,
+				.cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx),
+			},
+		},
+	},
+	{
+		.algonum = VIRTIO_CRYPTO_AKCIPHER_ECDSA,
+		.service = VIRTIO_CRYPTO_SERVICE_AKCIPHER,
+		.algo = {
+			.sign = virtio_crypto_akcipher_sign,
+			.verify = virtio_crypto_akcipher_verify,
+			.set_pub_key = virtio_crypto_ecdsa_nist_p256_set_pub_key,
+			.set_priv_key = virtio_crypto_ecdsa_nist_p256_set_priv_key,
+			.max_size = virtio_crypto_ecdsa_max_size,
+			.init = virtio_crypto_ecdsa_nist_p256_init_tfm,
+			.exit = virtio_crypto_ecdsa_exit_tfm,
+			.reqsize = sizeof(struct virtio_crypto_akcipher_request),
+			.base = {
+				.cra_name = "ecdsa-nist-p256",
+				.cra_driver_name = "virtio-ecdsa-nist-p256",
+				.cra_priority = 150,
+				.cra_module = THIS_MODULE,
+				.cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx),
+			},
+		},
+	},
+	{
+		.algonum = VIRTIO_CRYPTO_AKCIPHER_ECDSA,
+		.service = VIRTIO_CRYPTO_SERVICE_AKCIPHER,
+		.algo = {
+			.sign = virtio_crypto_akcipher_sign,
+			.verify = virtio_crypto_akcipher_verify,
+			.set_pub_key = virtio_crypto_ecdsa_nist_p384_set_pub_key,
+			.set_priv_key = virtio_crypto_ecdsa_nist_p384_set_priv_key,
+			.max_size = virtio_crypto_ecdsa_max_size,
+			.init = virtio_crypto_ecdsa_nist_p384_init_tfm,
+			.exit = virtio_crypto_ecdsa_exit_tfm,
+			.reqsize = sizeof(struct virtio_crypto_akcipher_request),
+			.base = {
+				.cra_name = "ecdsa-nist-p384",
+				.cra_driver_name = "virtio-ecdsa-nist-p384",
+				.cra_priority = 150,
+				.cra_module = THIS_MODULE,
+				.cra_ctxsize = sizeof(struct virtio_crypto_akcipher_ctx),
+			},
+		},
+
+	},
 };
 
 int virtio_crypto_akcipher_algs_register(struct virtio_crypto *vcrypto)
@@ -552,8 +771,7 @@ int virtio_crypto_akcipher_algs_register(struct virtio_crypto *vcrypto)
 
 		if (virtio_crypto_akcipher_algs[i].active_devs == 0) {
 			ret = crypto_register_akcipher(&virtio_crypto_akcipher_algs[i].algo);
-			if (ret)
-				goto unlock;
+			continue;
 		}
 
 		virtio_crypto_akcipher_algs[i].active_devs++;
@@ -561,7 +779,6 @@ int virtio_crypto_akcipher_algs_register(struct virtio_crypto *vcrypto)
 			 virtio_crypto_akcipher_algs[i].algo.base.cra_name);
 	}
 
-unlock:
 	mutex_unlock(&algs_lock);
 	return ret;
 }
-- 
2.20.1


  parent reply	other threads:[~2022-06-23  7:06 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-06-23  7:05 [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm Lei He
2022-06-23  7:05 ` [PATCH v2 1/4] crypto: fix the calculation of max_size for ECDSA Lei He
2022-06-23  7:05 ` [PATCH v2 2/4] crypto: pkcs8 parser support ECDSA private keys Lei He
2022-06-23  7:05 ` [PATCH v2 3/4] crypto: remove unused field in pkcs8_parse_context Lei He
2022-06-23  7:05 ` Lei He [this message]
2022-06-24  6:51 ` [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm Michael S. Tsirkin
2022-06-30  6:59 ` Herbert Xu
2022-06-30  7:23   ` [External] " Lei He
2022-06-30  7:41     ` Herbert Xu
2022-06-30  8:30       ` Lei He
2022-06-30  9:07         ` Herbert Xu
2022-06-30 12:44           ` Lei He
2022-06-30 12:50             ` Lei He
2022-06-30 23:12         ` Sandy Harris
2022-07-01  2:54           ` [External] " Lei He
2022-06-30  9:48     ` [External] " Daniel P. Berrangé
2022-06-30 12:43       ` Lei He
2022-08-09 18:36 ` Michael S. Tsirkin
  -- strict thread matches above, loose matches on Subject: below --
2022-06-23  6:14 [PATCH v2 1/4] crypto: fix the calculation of max_size for ECDSA Lei He
2022-06-23  6:15 ` [PATCH v2 4/4] virtio-crypto: support ECDSA algorithm Lei He

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220623070550.82053-5-helei.sig11@bytedance.com \
    --to=helei.sig11@bytedance.com \
    --cc=berrange@redhat.com \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=pizhenwei@bytedance.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).