2022-06-23 07:07:09

by Lei He

[permalink] [raw]
Subject: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

From: lei he <[email protected]>

This patch supports the ECDSA algorithm for virtio-crypto.

V1 -> V2:
- explicitly specified an appropriate base commit.
- fixed the link error reported by kernel test robot <[email protected]>.
- removed irrelevant commits.

V1:
- fixed the problem that the max_signature_size of ECDSA is
incorrectly calculated.
- make pkcs8_private_key_parser can identify ECDSA private keys.
- implement ECDSA algorithm for virtio-crypto device


lei he (4):
crypto: fix the calculation of max_size for ECDSA
crypto: pkcs8 parser support ECDSA private keys
crypto: remove unused field in pkcs8_parse_context
virtio-crypto: support ECDSA algorithm

crypto/Kconfig | 1 +
crypto/Makefile | 2 +
crypto/akcipher.c | 10 +
crypto/asymmetric_keys/pkcs8.asn1 | 2 +-
crypto/asymmetric_keys/pkcs8_parser.c | 46 +++-
crypto/ecdsa.c | 3 +-
crypto/ecdsa_helper.c | 45 +++
drivers/crypto/virtio/Kconfig | 1 +
.../virtio/virtio_crypto_akcipher_algs.c | 259 ++++++++++++++++--
include/crypto/internal/ecdsa.h | 15 +
include/linux/asn1_encoder.h | 2 +
lib/asn1_encoder.c | 3 +-
12 files changed, 361 insertions(+), 28 deletions(-)
create mode 100644 crypto/ecdsa_helper.c
create mode 100644 include/crypto/internal/ecdsa.h


base-commit: 018ab4fabddd94f1c96f3b59e180691b9e88d5d8
--
2.20.1


2022-06-23 07:07:14

by Lei He

[permalink] [raw]
Subject: [PATCH v2 2/4] crypto: pkcs8 parser support ECDSA private keys

From: lei he <[email protected]>

Make pkcs8_private_key_parser can identify ECDSA private keys.

Signed-off-by: lei he <[email protected]>
---
crypto/akcipher.c | 10 ++++++
crypto/asymmetric_keys/pkcs8.asn1 | 2 +-
crypto/asymmetric_keys/pkcs8_parser.c | 45 +++++++++++++++++++++++++--
3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/crypto/akcipher.c b/crypto/akcipher.c
index f866085c8a4a..3adcdc6d48c2 100644
--- a/crypto/akcipher.c
+++ b/crypto/akcipher.c
@@ -120,6 +120,12 @@ static int akcipher_default_op(struct akcipher_request *req)
return -ENOSYS;
}

+static int akcipher_default_set_key(struct crypto_akcipher *tfm,
+ const void *key, unsigned int keylen)
+{
+ return -ENOSYS;
+}
+
int crypto_register_akcipher(struct akcipher_alg *alg)
{
struct crypto_alg *base = &alg->base;
@@ -132,6 +138,10 @@ int crypto_register_akcipher(struct akcipher_alg *alg)
alg->encrypt = akcipher_default_op;
if (!alg->decrypt)
alg->decrypt = akcipher_default_op;
+ if (!alg->set_pub_key)
+ alg->set_pub_key = akcipher_default_set_key;
+ if (!alg->set_priv_key)
+ alg->set_priv_key = akcipher_default_set_key;

akcipher_prepare_alg(alg);
return crypto_register_alg(base);
diff --git a/crypto/asymmetric_keys/pkcs8.asn1 b/crypto/asymmetric_keys/pkcs8.asn1
index 702c41a3c713..1791ddf4168a 100644
--- a/crypto/asymmetric_keys/pkcs8.asn1
+++ b/crypto/asymmetric_keys/pkcs8.asn1
@@ -20,5 +20,5 @@ Attribute ::= ANY

AlgorithmIdentifier ::= SEQUENCE {
algorithm OBJECT IDENTIFIER ({ pkcs8_note_OID }),
- parameters ANY OPTIONAL
+ parameters ANY OPTIONAL ({ pkcs8_note_algo_parameter })
}
diff --git a/crypto/asymmetric_keys/pkcs8_parser.c b/crypto/asymmetric_keys/pkcs8_parser.c
index 105dcce27f71..e507c635ead5 100644
--- a/crypto/asymmetric_keys/pkcs8_parser.c
+++ b/crypto/asymmetric_keys/pkcs8_parser.c
@@ -24,6 +24,8 @@ struct pkcs8_parse_context {
enum OID algo_oid; /* Algorithm OID */
u32 key_size;
const void *key;
+ const void *algo_param;
+ u32 algo_param_len;
};

/*
@@ -47,6 +49,17 @@ int pkcs8_note_OID(void *context, size_t hdrlen,
return 0;
}

+int pkcs8_note_algo_parameter(void *context, size_t hdrlen,
+ unsigned char tag,
+ const void *value, size_t vlen)
+{
+ struct pkcs8_parse_context *ctx = context;
+
+ ctx->algo_param = value;
+ ctx->algo_param_len = vlen;
+ return 0;
+}
+
/*
* Note the version number of the ASN.1 blob.
*/
@@ -69,11 +82,37 @@ int pkcs8_note_algo(void *context, size_t hdrlen,
const void *value, size_t vlen)
{
struct pkcs8_parse_context *ctx = context;
-
- if (ctx->last_oid != OID_rsaEncryption)
+ enum OID curve_id;
+
+ switch (ctx->last_oid) {
+ case OID_id_ecPublicKey:
+ if (!ctx->algo_param || ctx->algo_param_len == 0)
+ return -EBADMSG;
+ curve_id = look_up_OID(ctx->algo_param, ctx->algo_param_len);
+
+ switch (curve_id) {
+ case OID_id_prime192v1:
+ ctx->pub->pkey_algo = "ecdsa-nist-p192";
+ break;
+ case OID_id_prime256v1:
+ ctx->pub->pkey_algo = "ecdsa-nist-p256";
+ break;
+ case OID_id_ansip384r1:
+ ctx->pub->pkey_algo = "ecdsa-nist-p384";
+ break;
+ default:
+ return -ENOPKG;
+ }
+ break;
+
+ case OID_rsaEncryption:
+ ctx->pub->pkey_algo = "rsa";
+ break;
+
+ default:
return -ENOPKG;
+ }

- ctx->pub->pkey_algo = "rsa";
return 0;
}

--
2.20.1

2022-06-23 07:08:08

by Lei He

[permalink] [raw]
Subject: [PATCH v2 3/4] crypto: remove unused field in pkcs8_parse_context

From: lei he <[email protected]>

remove unused field 'algo_oid' in pkcs8_parse_context

Signed-off-by: lei he <[email protected]>
---
crypto/asymmetric_keys/pkcs8_parser.c | 1 -
1 file changed, 1 deletion(-)

diff --git a/crypto/asymmetric_keys/pkcs8_parser.c b/crypto/asymmetric_keys/pkcs8_parser.c
index e507c635ead5..f81317234331 100644
--- a/crypto/asymmetric_keys/pkcs8_parser.c
+++ b/crypto/asymmetric_keys/pkcs8_parser.c
@@ -21,7 +21,6 @@ struct pkcs8_parse_context {
struct public_key *pub;
unsigned long data; /* Start of data */
enum OID last_oid; /* Last OID encountered */
- enum OID algo_oid; /* Algorithm OID */
u32 key_size;
const void *key;
const void *algo_param;
--
2.20.1

2022-06-23 07:08:13

by Lei He

[permalink] [raw]
Subject: [PATCH v2 4/4] virtio-crypto: support ECDSA algorithm

From: lei he <[email protected]>

Support ECDSA algorithm for driver virtio-crypto

Signed-off-by: lei he <[email protected]>
---
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

2022-06-24 06:57:33

by Michael S. Tsirkin

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Thu, Jun 23, 2022 at 03:05:46PM +0800, Lei He wrote:
> From: lei he <[email protected]>
>
> This patch supports the ECDSA algorithm for virtio-crypto.

virtio parts:

Acked-by: Michael S. Tsirkin <[email protected]>

> V1 -> V2:
> - explicitly specified an appropriate base commit.
> - fixed the link error reported by kernel test robot <[email protected]>.
> - removed irrelevant commits.
>
> V1:
> - fixed the problem that the max_signature_size of ECDSA is
> incorrectly calculated.
> - make pkcs8_private_key_parser can identify ECDSA private keys.
> - implement ECDSA algorithm for virtio-crypto device
>
>
> lei he (4):
> crypto: fix the calculation of max_size for ECDSA
> crypto: pkcs8 parser support ECDSA private keys
> crypto: remove unused field in pkcs8_parse_context
> virtio-crypto: support ECDSA algorithm
>
> crypto/Kconfig | 1 +
> crypto/Makefile | 2 +
> crypto/akcipher.c | 10 +
> crypto/asymmetric_keys/pkcs8.asn1 | 2 +-
> crypto/asymmetric_keys/pkcs8_parser.c | 46 +++-
> crypto/ecdsa.c | 3 +-
> crypto/ecdsa_helper.c | 45 +++
> drivers/crypto/virtio/Kconfig | 1 +
> .../virtio/virtio_crypto_akcipher_algs.c | 259 ++++++++++++++++--
> include/crypto/internal/ecdsa.h | 15 +
> include/linux/asn1_encoder.h | 2 +
> lib/asn1_encoder.c | 3 +-
> 12 files changed, 361 insertions(+), 28 deletions(-)
> create mode 100644 crypto/ecdsa_helper.c
> create mode 100644 include/crypto/internal/ecdsa.h
>
>
> base-commit: 018ab4fabddd94f1c96f3b59e180691b9e88d5d8
> --
> 2.20.1

2022-06-30 07:02:31

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Thu, Jun 23, 2022 at 03:05:46PM +0800, Lei He wrote:
> From: lei he <[email protected]>
>
> This patch supports the ECDSA algorithm for virtio-crypto.

Why is this necessary?

Thanks,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2022-06-30 07:29:54

by Lei He

[permalink] [raw]
Subject: Re: [External] [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm


> On Jun 30, 2022, at 2:59 PM, Herbert Xu <[email protected]> wrote:
>
> On Thu, Jun 23, 2022 at 03:05:46PM +0800, Lei He wrote:
>> From: lei he <[email protected]>
>>
>> This patch supports the ECDSA algorithm for virtio-crypto.
>
> Why is this necessary?
>

The main purpose of this patch is to offload ECDSA computations to virtio-crypto dev.
We can modify the backend of virtio-crypto to allow hardware like Intel QAT cards to
perform the actual calculations, and user-space applications such as HTTPS server
can access those backend in a unified way(eg, keyctl_pk_xx syscall).

Related works are also described in following patch series:
https://lwn.net/ml/linux-crypto/[email protected]/

> Thanks,
> --
> Email: Herbert Xu <[email protected]>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2022-06-30 07:42:31

by Herbert Xu

[permalink] [raw]
Subject: Re: [External] [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Thu, Jun 30, 2022 at 03:23:39PM +0800, Lei He wrote:
>
> The main purpose of this patch is to offload ECDSA computations to virtio-crypto dev.
> We can modify the backend of virtio-crypto to allow hardware like Intel QAT cards to
> perform the actual calculations, and user-space applications such as HTTPS server
> can access those backend in a unified way(eg, keyctl_pk_xx syscall).

The things is I don't see any driver support in the kernel for
ECDSA.

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2022-06-30 08:37:27

by Lei He

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm


> On Jun 30, 2022, at 3:41 PM, Herbert Xu <[email protected]> wrote:
>
> The things is I don't see any driver support in the kernel for
> ECDSA.
>

I have explained above why we need a driver that supports ECDSA, and this patch
enables virtio-crypto to support ECDSA. I think this is a good time to support ECDSA
in the kernel crypto framework, and there will be more drivers supporting ECDSA in the
future.
Looking forward to your opinion :-).

2022-06-30 09:14:56

by Herbert Xu

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Thu, Jun 30, 2022 at 04:30:39PM +0800, Lei He wrote:
>
> I have explained above why we need a driver that supports ECDSA, and this patch
> enables virtio-crypto to support ECDSA. I think this is a good time to support ECDSA
> in the kernel crypto framework, and there will be more drivers supporting ECDSA in the
> future.
> Looking forward to your opinion :-).

Until there are drivers in the kernel it's pointless to implement
this.

Cheers,
--
Email: Herbert Xu <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt

2022-06-30 12:46:42

by Lei He

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Jun 30, 2022, at 5:48 PM, Daniel P. Berrangé <[email protected]> wrote:
>
> On Thu, Jun 30, 2022 at 03:23:39PM +0800, Lei He wrote:
>>
>>> On Jun 30, 2022, at 2:59 PM, Herbert Xu <[email protected]> wrote:
>>>
>>> On Thu, Jun 23, 2022 at 03:05:46PM +0800, Lei He wrote:
>>>> From: lei he <[email protected]>
>>>>
>>>> This patch supports the ECDSA algorithm for virtio-crypto.
>>>
>>> Why is this necessary?
>>>
>>
>> The main purpose of this patch is to offload ECDSA computations to virtio-crypto dev.
>> We can modify the backend of virtio-crypto to allow hardware like Intel QAT cards to
>> perform the actual calculations, and user-space applications such as HTTPS server
>> can access those backend in a unified way(eg, keyctl_pk_xx syscall).
>>
>> Related works are also described in following patch series:
>> https://lwn.net/ml/linux-crypto/[email protected]/
>
> IIUC, this link refers to testing performance of the RSA impl of
> virtio-crypto with a vhost-user backend, leveraging an Intel QAT
> device on the host. What's the status of that depolyment setup ?
> Is code for it published anywhere, and does it have dependancy on
> any kernel patches that are not yet posted and/or merged ? Does it
> cover both ECDSA and RSA yet, or still only RSA ?
>
> The QEMU backend part of the virtio-crypto support for ECDSA looks fine
> to merge, but obviously I'd like some positive sign that the kernel
> maintainers are willing to accept the guest driver side.
>

1. We have now been able to provide offload capability for nginx’s TLS handshake in the virtual
machine(with the kctl-engine), and have achieved about 0.8~0.9 times performance improvement.
But as you can see, when we were testing, both authentication and key exchange only supported
RSA at the moment.
2. The code for the QAT offload backend is not posted now, it does not support the ECDSA, so it also does not
depends on any other patches that have not been merged. To support ECDSA, this patch is required.
At present, I have only implemented and tested the ECDSA for the builtin backend, and the ECDSA support
for another backend that can offload is also in progress.

By the way, the virtio part of QEMU( for support ECDSA) is also ready, I will post it soon.

2022-06-30 12:46:52

by Lei He

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Jun 30, 2022, at 5:07 PM, Herbert Xu <[email protected]> wrote:

>
> On Thu, Jun 30, 2022 at 04:30:39PM +0800, Lei He wrote:
>>
>> I have explained above why we need a driver that supports ECDSA, and this patch
>> enables virtio-crypto to support ECDSA. I think this is a good time to support ECDSA
>> in the kernel crypto framework, and there will be more drivers supporting ECDSA in the
>> future.
>> Looking forward to your opinion :-).
>
> Until there are drivers in the kernel it's pointless to implement
> this.
>

I guess you mean that if there are no drivers in the linux kernel source tree that supports the
ECDSA, then there is no way under linux to offload ECDSA to other devices, so even if the
virtio-crypto can get the akcipher request, it can’t do better, right? I have some different opinions
on this:
1. There does exist hardware for offloading ECDSA calculations, for example, IBM PCIe
Cryptographic Coprocessor, Intel QAT, etc, and those chips are already on the market now.
Of course, they also provided corresponding drivers to access these devices, but for some reason,
these drivers have not been submitted to the kernel source tree now.
2. With this patch, when we use QEMU to create a virtual machine, people can directly access the
virtio-crypto device without caring about where these akcipher requests are executed, and no need
to update drivers(and other stuff) for guest kernel when the co-processor is updated.
3. I will communicate with the Intel QAT team about their plans to provide ECDSA support and ECDH
support.


2022-06-30 12:54:57

by Lei He

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Jun 30, 2022, at 8:44 PM, Lei He <[email protected]> wrote:
>
> On Jun 30, 2022, at 5:07 PM, Herbert Xu <[email protected]> wrote:
>
>>
>> On Thu, Jun 30, 2022 at 04:30:39PM +0800, Lei He wrote:
>>>
>>> I have explained above why we need a driver that supports ECDSA, and this patch
>>> enables virtio-crypto to support ECDSA. I think this is a good time to support ECDSA
>>> in the kernel crypto framework, and there will be more drivers supporting ECDSA in the
>>> future.
>>> Looking forward to your opinion :-).
>>
>> Until there are drivers in the kernel it's pointless to implement
>> this.
>>
>
> I guess you mean that if there are no drivers in the linux kernel source tree that supports the
> ECDSA, then there is no way under linux to offload ECDSA to other devices, so even if the
> virtio-crypto can get the akcipher request, it can’t do better, right? I have some different opinions
> on this:
> 1. There does exist hardware for offloading ECDSA calculations, for example, IBM PCIe
> Cryptographic Coprocessor, Intel QAT, etc, and those chips are already on the market now.
> Of course, they also provided corresponding drivers to access these devices, but for some reason,
> these drivers have not been submitted to the kernel source tree now.
> 2. With this patch, when we use QEMU to create a virtual machine, people can directly access the
> virtio-crypto device without caring about where these akcipher requests are executed, and no need
> to update drivers(and other stuff) for guest kernel when the co-processor is updated.
> 3. I will communicate with the Intel QAT team about their plans to provide ECDSA support and ECDH
> support.

Hi, xin:
I would like to ask if you have any plans to support ECDSA in LKC for QAT driver, and if so how is
it going?

2022-06-30 23:14:15

by Sandy Harris

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Thu, Jun 30, 2022 at 4:37 PM Lei He <[email protected]> wrote:

> I have explained above why we need a driver that supports ECDSA, ...

I do not think we do. There are some security concerns.
https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Security

2022-07-01 02:58:47

by Lei He

[permalink] [raw]
Subject: Re: [External] Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On 7/1/2022 7:12 AM, Sandy Harris wrote:
> On Thu, Jun 30, 2022 at 4:37 PM Lei He <[email protected]> wrote:
>
>> I have explained above why we need a driver that supports ECDSA, ...
>
> I do not think we do. There are some security concerns.
> https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Security

But since tls1.0, the ECDSA algorithm has been retained to the current
1.3 version.
https://en.wikipedia.org/wiki/Transport_Layer_Security#Algorithms

Best regards,
Lei He
--
[email protected]

2022-08-09 19:06:40

by Michael S. Tsirkin

[permalink] [raw]
Subject: Re: [PATCH v2 0/4] virtio-crypto: support ECDSA algorithm

On Thu, Jun 23, 2022 at 03:05:46PM +0800, Lei He wrote:
> From: lei he <[email protected]>
>
> This patch supports the ECDSA algorithm for virtio-crypto.
>
> V1 -> V2:
> - explicitly specified an appropriate base commit.
> - fixed the link error reported by kernel test robot <[email protected]>.
> - removed irrelevant commits.
>
> V1:
> - fixed the problem that the max_signature_size of ECDSA is
> incorrectly calculated.
> - make pkcs8_private_key_parser can identify ECDSA private keys.
> - implement ECDSA algorithm for virtio-crypto device


So this depends on core crypto changes that need Herbert's ack.
I'll drop this from my radar for now.

>
> lei he (4):
> crypto: fix the calculation of max_size for ECDSA
> crypto: pkcs8 parser support ECDSA private keys
> crypto: remove unused field in pkcs8_parse_context
> virtio-crypto: support ECDSA algorithm
>
> crypto/Kconfig | 1 +
> crypto/Makefile | 2 +
> crypto/akcipher.c | 10 +
> crypto/asymmetric_keys/pkcs8.asn1 | 2 +-
> crypto/asymmetric_keys/pkcs8_parser.c | 46 +++-
> crypto/ecdsa.c | 3 +-
> crypto/ecdsa_helper.c | 45 +++
> drivers/crypto/virtio/Kconfig | 1 +
> .../virtio/virtio_crypto_akcipher_algs.c | 259 ++++++++++++++++--
> include/crypto/internal/ecdsa.h | 15 +
> include/linux/asn1_encoder.h | 2 +
> lib/asn1_encoder.c | 3 +-
> 12 files changed, 361 insertions(+), 28 deletions(-)
> create mode 100644 crypto/ecdsa_helper.c
> create mode 100644 include/crypto/internal/ecdsa.h
>
>
> base-commit: 018ab4fabddd94f1c96f3b59e180691b9e88d5d8
> --
> 2.20.1