2022-06-17 07:09:04

by Lei He

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

From: lei he <[email protected]>

This patch supports the ECDSA algorithm for virtio-crypto:
1. fixed the problem that the max_signature_size of ECDSA is
incorrectly calculated.
2. make pkcs8_private_key_parser can identify ECDSA private keys.
3. 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 +++
.../virtio/virtio_crypto_akcipher_algs.c | 259 ++++++++++++++++--
include/crypto/internal/ecdsa.h | 15 +
include/linux/asn1_encoder.h | 2 +
lib/asn1_encoder.c | 3 +-
11 files changed, 360 insertions(+), 28 deletions(-)
create mode 100644 crypto/ecdsa_helper.c
create mode 100644 include/crypto/internal/ecdsa.h

--
2.20.1


2022-06-17 07:09:04

by Lei He

[permalink] [raw]
Subject: [PATCH] crypto: testmgr - fix version number of RSA tests

From: lei he <[email protected]>

According to PKCS#1 standard, the 'otherPrimeInfos' field contains
the information for the additional primes r_3, ..., r_u, in order.
It shall be omitted if the version is 0 and shall contain at least
one instance of OtherPrimeInfo if the version is 1, see:
https://www.rfc-editor.org/rfc/rfc3447#page-44

Replace the version number '1' with 0, otherwise, some drivers may
not pass the run-time tests.

Signed-off-by: lei he <[email protected]>
---
crypto/testmgr.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index 4d7449fc6a65..d57f24b906f1 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -186,7 +186,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
#ifndef CONFIG_CRYPTO_FIPS
.key =
"\x30\x81\x9A" /* sequence of 154 bytes */
- "\x02\x01\x01" /* version - integer of 1 byte */
+ "\x02\x01\x00" /* version - integer of 1 byte */
"\x02\x41" /* modulus - integer of 65 bytes */
"\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
"\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
@@ -216,7 +216,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
}, {
.key =
"\x30\x82\x01\x1D" /* sequence of 285 bytes */
- "\x02\x01\x01" /* version - integer of 1 byte */
+ "\x02\x01\x00" /* version - integer of 1 byte */
"\x02\x81\x81" /* modulus - integer of 129 bytes */
"\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71"
"\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5"
@@ -260,7 +260,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
#endif
.key =
"\x30\x82\x02\x20" /* sequence of 544 bytes */
- "\x02\x01\x01" /* version - integer of 1 byte */
+ "\x02\x01\x00" /* version - integer of 1 byte */
"\x02\x82\x01\x01\x00" /* modulus - integer of 256 bytes */
"\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D"
"\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA"
--
2.20.1

2022-06-17 07:09:06

by Lei He

[permalink] [raw]
Subject: [PATCH 1/4] crypto: fix the calculation of max_size for ECDSA

From: lei he <[email protected]>

The signature of ECDSA is consists of two big integers up to the
size of keylen, and is DER encoded into one SEQUENCE.
Calculate max_size of ECDSA signature more accurately according to
the DER encoding rules.

Signed-off-by: lei he <[email protected]>
---
crypto/Kconfig | 1 +
crypto/Makefile | 2 ++
crypto/ecdsa.c | 3 ++-
crypto/ecdsa_helper.c | 45 +++++++++++++++++++++++++++++++++
include/crypto/internal/ecdsa.h | 15 +++++++++++
include/linux/asn1_encoder.h | 2 ++
lib/asn1_encoder.c | 3 ++-
7 files changed, 69 insertions(+), 2 deletions(-)
create mode 100644 crypto/ecdsa_helper.c
create mode 100644 include/crypto/internal/ecdsa.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 41068811fd0e..b54d067602cc 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -254,6 +254,7 @@ config CRYPTO_ECDSA
select CRYPTO_ECC
select CRYPTO_AKCIPHER
select ASN1
+ select ASN1_ENCODER
help
Elliptic Curve Digital Signature Algorithm (NIST P192, P256 etc.)
is A NIST cryptographic standard algorithm. Only signature verification
diff --git a/crypto/Makefile b/crypto/Makefile
index f754c4d17d6b..b59b15ee087c 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -52,8 +52,10 @@ obj-$(CONFIG_CRYPTO_SM2) += sm2_generic.o

$(obj)/ecdsasignature.asn1.o: $(obj)/ecdsasignature.asn1.c $(obj)/ecdsasignature.asn1.h
$(obj)/ecdsa.o: $(obj)/ecdsasignature.asn1.h
+
ecdsa_generic-y += ecdsa.o
ecdsa_generic-y += ecdsasignature.asn1.o
+ecdsa_generic-y += ecdsa_helper.o
obj-$(CONFIG_CRYPTO_ECDSA) += ecdsa_generic.o

crypto_acompress-y := acompress.o
diff --git a/crypto/ecdsa.c b/crypto/ecdsa.c
index b3a8a6b572ba..2ba44c92d271 100644
--- a/crypto/ecdsa.c
+++ b/crypto/ecdsa.c
@@ -6,6 +6,7 @@
#include <linux/module.h>
#include <crypto/internal/akcipher.h>
#include <crypto/internal/ecc.h>
+#include <crypto/internal/ecdsa.h>
#include <crypto/akcipher.h>
#include <crypto/ecdh.h>
#include <linux/asn1_decoder.h>
@@ -262,7 +263,7 @@ static unsigned int ecdsa_max_size(struct crypto_akcipher *tfm)
{
struct ecc_ctx *ctx = akcipher_tfm_ctx(tfm);

- return ctx->pub_key.ndigits << ECC_DIGITS_TO_BYTES_SHIFT;
+ return ecdsa_max_signature_size(ctx->curve);
}

static int ecdsa_nist_p384_init_tfm(struct crypto_akcipher *tfm)
diff --git a/crypto/ecdsa_helper.c b/crypto/ecdsa_helper.c
new file mode 100644
index 000000000000..487c4e9c0f67
--- /dev/null
+++ b/crypto/ecdsa_helper.c
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * RSA key extract helper
+ *
+ * Copyright 2022 Bytedance CO., LTD.
+ *
+ * Authors: lei he <[email protected]>
+ */
+#include <crypto/internal/ecdsa.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/oid_registry.h>
+#include <linux/asn1_encoder.h>
+#include <crypto/ecdh.h>
+
+unsigned int ecdsa_max_signature_size(const struct ecc_curve *curve)
+{
+ unsigned int keylen = curve->g.ndigits * sizeof(u64);
+ /* Up to one extra byte to indicate the format */
+ unsigned char buffer[sizeof(size_t) + 1], *data = buffer;
+ int buffer_len = sizeof(buffer);
+ unsigned int coordinate_length, sequence_length;
+
+ asn1_encode_length(&data, &buffer_len, keylen);
+ /**
+ * The extra cost for encoding keylen bytes as INTEGER in ASN.1:
+ * 1. one byte for tag
+ * 2. sizeof(buffer) - buffer_len bytes for length
+ * 3. one leading zero byte for integers whose leftmost bit is 1
+ */
+ coordinate_length = 1 + sizeof(buffer) - buffer_len + 1 + keylen;
+
+ /**
+ * The extra cost for encoding coordinate_length * 2 bytes as SEQUENCE in ASN.1:
+ * 1. one byte for tag
+ * 2. sizeof(buffer) - buffer_len bytes for length
+ */
+ buffer_len = sizeof(buffer);
+ data = buffer;
+ asn1_encode_length(&data, &buffer_len, coordinate_length * 2);
+ sequence_length = 1 + sizeof(buffer) - buffer_len + coordinate_length * 2;
+
+ return sequence_length;
+}
+EXPORT_SYMBOL_GPL(ecdsa_max_signature_size);
diff --git a/include/crypto/internal/ecdsa.h b/include/crypto/internal/ecdsa.h
new file mode 100644
index 000000000000..e35638a35dc2
--- /dev/null
+++ b/include/crypto/internal/ecdsa.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ECDSA internal helpers
+ *
+ * Copyright (c) 2022 lei he <[email protected]>
+ */
+
+ #ifndef _CRYPTO_ECDSA_H
+ #define _CRYPTO_ECDSA_H
+
+#include <crypto/ecc_curve.h>
+
+unsigned int ecdsa_max_signature_size(const struct ecc_curve *curve);
+
+#endif
diff --git a/include/linux/asn1_encoder.h b/include/linux/asn1_encoder.h
index 08cd0c2ad34f..fe439c9a73e3 100644
--- a/include/linux/asn1_encoder.h
+++ b/include/linux/asn1_encoder.h
@@ -29,4 +29,6 @@ unsigned char *
asn1_encode_boolean(unsigned char *data, const unsigned char *end_data,
bool val);

+int asn1_encode_length(unsigned char **data, int *data_len, int len);
+
#endif
diff --git a/lib/asn1_encoder.c b/lib/asn1_encoder.c
index 0fd3c454a468..644af3055ebb 100644
--- a/lib/asn1_encoder.c
+++ b/lib/asn1_encoder.c
@@ -188,7 +188,7 @@ EXPORT_SYMBOL_GPL(asn1_encode_oid);
* encoder primitives to accept negative lengths as singalling the
* sequence will be re-encoded when the length is known.
*/
-static int asn1_encode_length(unsigned char **data, int *data_len, int len)
+int asn1_encode_length(unsigned char **data, int *data_len, int len)
{
if (*data_len < 1)
return -EINVAL;
@@ -239,6 +239,7 @@ static int asn1_encode_length(unsigned char **data, int *data_len, int len)

return 0;
}
+EXPORT_SYMBOL_GPL(asn1_encode_length);

/**
* asn1_encode_tag() - add a tag for optional or explicit value
--
2.20.1

2022-06-17 07:09:17

by Lei He

[permalink] [raw]
Subject: [PATCH 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-17 07:09:44

by Lei He

[permalink] [raw]
Subject: [PATCH 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]>
---
.../virtio/virtio_crypto_akcipher_algs.c | 259 ++++++++++++++++--
1 file changed, 238 insertions(+), 21 deletions(-)

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-17 07:10:21

by Lei He

[permalink] [raw]
Subject: [PATCH 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-17 11:08:13

by Michael S. Tsirkin

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

On Fri, Jun 17, 2022 at 03:07:49PM +0800, Lei He wrote:
> From: lei he <[email protected]>
>
> This patch supports the ECDSA algorithm for virtio-crypto:
> 1. fixed the problem that the max_signature_size of ECDSA is
> incorrectly calculated.
> 2. make pkcs8_private_key_parser can identify ECDSA private keys.
> 3. implement ECDSA algorithm for virtio-crypto device

virtio bits:

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


> 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 +++
> .../virtio/virtio_crypto_akcipher_algs.c | 259 ++++++++++++++++--
> include/crypto/internal/ecdsa.h | 15 +
> include/linux/asn1_encoder.h | 2 +
> lib/asn1_encoder.c | 3 +-
> 11 files changed, 360 insertions(+), 28 deletions(-)
> create mode 100644 crypto/ecdsa_helper.c
> create mode 100644 include/crypto/internal/ecdsa.h
>
> --
> 2.20.1

2022-06-17 14:47:22

by kernel test robot

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

Hi Lei,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on herbert-cryptodev-2.6/master]
[also build test ERROR on herbert-crypto-2.6/master linus/master v5.19-rc2 next-20220617]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/intel-lab-lkp/linux/commits/Lei-He/virtio-crypto-support-ECDSA-algorithm/20220617-151113
base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: i386-randconfig-m021 (https://download.01.org/0day-ci/archive/20220617/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce (this is a W=1 build):
# https://github.com/intel-lab-lkp/linux/commit/d335068e54f1217848445185702d75739116b1fe
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Lei-He/virtio-crypto-support-ECDSA-algorithm/20220617-151113
git checkout d335068e54f1217848445185702d75739116b1fe
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>):

ld: drivers/crypto/virtio/virtio_crypto_akcipher_algs.o: in function `virtio_crypto_ecdsa_max_size':
>> drivers/crypto/virtio/virtio_crypto_akcipher_algs.c:602: undefined reference to `ecdsa_max_signature_size'


vim +602 drivers/crypto/virtio/virtio_crypto_akcipher_algs.c

596
597 static unsigned int virtio_crypto_ecdsa_max_size(struct crypto_akcipher *tfm)
598 {
599 struct virtio_crypto_akcipher_ctx *ctx = akcipher_tfm_ctx(tfm);
600 struct virtio_crypto_ecdsa_ctx *ecdsa_ctx = &ctx->ecdsa_ctx;
601
> 602 return ecdsa_max_signature_size(ecdsa_ctx->curve);
603 }
604

--
0-DAY CI Kernel Test Service
https://01.org/lkp

2022-06-17 17:52:13

by kernel test robot

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

Hi Lei,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on herbert-cryptodev-2.6/master]
[also build test ERROR on herbert-crypto-2.6/master linus/master v5.19-rc2 next-20220617]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/intel-lab-lkp/linux/commits/Lei-He/virtio-crypto-support-ECDSA-algorithm/20220617-151113
base: https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git master
config: i386-randconfig-s001 (https://download.01.org/0day-ci/archive/20220618/[email protected]/config)
compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
reproduce:
# apt-get install sparse
# sparse version: v0.6.4-30-g92122700-dirty
# https://github.com/intel-lab-lkp/linux/commit/d335068e54f1217848445185702d75739116b1fe
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Lei-He/virtio-crypto-support-ECDSA-algorithm/20220617-151113
git checkout d335068e54f1217848445185702d75739116b1fe
# save the config file
mkdir build_dir && cp config build_dir/.config
make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot <[email protected]>

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "ecdsa_max_signature_size" [drivers/crypto/virtio/virtio_crypto.ko] undefined!

--
0-DAY CI Kernel Test Service
https://01.org/lkp

2022-06-19 07:15:39

by Michael S. Tsirkin

[permalink] [raw]
Subject: Re: [PATCH] crypto: testmgr - fix version number of RSA tests

On Fri, Jun 17, 2022 at 03:07:51PM +0800, Lei He wrote:
> From: lei he <[email protected]>
>
> According to PKCS#1 standard, the 'otherPrimeInfos' field contains
> the information for the additional primes r_3, ..., r_u, in order.
> It shall be omitted if the version is 0 and shall contain at least
> one instance of OtherPrimeInfo if the version is 1, see:
> https://www.rfc-editor.org/rfc/rfc3447#page-44
>
> Replace the version number '1' with 0, otherwise, some drivers may
> not pass the run-time tests.
>
> Signed-off-by: lei he <[email protected]>

Why is this posted as part of the virtio-crypto patchset thread though?


> ---
> crypto/testmgr.h | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
> index 4d7449fc6a65..d57f24b906f1 100644
> --- a/crypto/testmgr.h
> +++ b/crypto/testmgr.h
> @@ -186,7 +186,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
> #ifndef CONFIG_CRYPTO_FIPS
> .key =
> "\x30\x81\x9A" /* sequence of 154 bytes */
> - "\x02\x01\x01" /* version - integer of 1 byte */
> + "\x02\x01\x00" /* version - integer of 1 byte */
> "\x02\x41" /* modulus - integer of 65 bytes */
> "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
> "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
> @@ -216,7 +216,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
> }, {
> .key =
> "\x30\x82\x01\x1D" /* sequence of 285 bytes */
> - "\x02\x01\x01" /* version - integer of 1 byte */
> + "\x02\x01\x00" /* version - integer of 1 byte */
> "\x02\x81\x81" /* modulus - integer of 129 bytes */
> "\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71"
> "\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5"
> @@ -260,7 +260,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
> #endif
> .key =
> "\x30\x82\x02\x20" /* sequence of 544 bytes */
> - "\x02\x01\x01" /* version - integer of 1 byte */
> + "\x02\x01\x00" /* version - integer of 1 byte */
> "\x02\x82\x01\x01\x00" /* modulus - integer of 256 bytes */
> "\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D"
> "\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA"
> --
> 2.20.1

2022-06-20 03:02:29

by Lei He

[permalink] [raw]
Subject: Re: [External] [PATCH] crypto: testmgr - fix version number of RSA tests

My mistake, please ignore this commit. I will resubmit and fix the bug reported by the bot

> On Jun 19, 2022, at 3:09 PM, Michael S. Tsirkin <[email protected]> wrote:
>
> On Fri, Jun 17, 2022 at 03:07:51PM +0800, Lei He wrote:
>> From: lei he <[email protected]>
>>
>> According to PKCS#1 standard, the 'otherPrimeInfos' field contains
>> the information for the additional primes r_3, ..., r_u, in order.
>> It shall be omitted if the version is 0 and shall contain at least
>> one instance of OtherPrimeInfo if the version is 1, see:
>> https://www.rfc-editor.org/rfc/rfc3447#page-44
>>
>> Replace the version number '1' with 0, otherwise, some drivers may
>> not pass the run-time tests.
>>
>> Signed-off-by: lei he <[email protected]>
>
> Why is this posted as part of the virtio-crypto patchset thread though?
>
>
>> ---
>> crypto/testmgr.h | 6 +++---
>> 1 file changed, 3 insertions(+), 3 deletions(-)
>>
>> diff --git a/crypto/testmgr.h b/crypto/testmgr.h
>> index 4d7449fc6a65..d57f24b906f1 100644
>> --- a/crypto/testmgr.h
>> +++ b/crypto/testmgr.h
>> @@ -186,7 +186,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
>> #ifndef CONFIG_CRYPTO_FIPS
>> .key =
>> "\x30\x81\x9A" /* sequence of 154 bytes */
>> - "\x02\x01\x01" /* version - integer of 1 byte */
>> + "\x02\x01\x00" /* version - integer of 1 byte */
>> "\x02\x41" /* modulus - integer of 65 bytes */
>> "\x00\xAA\x36\xAB\xCE\x88\xAC\xFD\xFF\x55\x52\x3C\x7F\xC4\x52\x3F"
>> "\x90\xEF\xA0\x0D\xF3\x77\x4A\x25\x9F\x2E\x62\xB4\xC5\xD9\x9C\xB5"
>> @@ -216,7 +216,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
>> }, {
>> .key =
>> "\x30\x82\x01\x1D" /* sequence of 285 bytes */
>> - "\x02\x01\x01" /* version - integer of 1 byte */
>> + "\x02\x01\x00" /* version - integer of 1 byte */
>> "\x02\x81\x81" /* modulus - integer of 129 bytes */
>> "\x00\xBB\xF8\x2F\x09\x06\x82\xCE\x9C\x23\x38\xAC\x2B\x9D\xA8\x71"
>> "\xF7\x36\x8D\x07\xEE\xD4\x10\x43\xA4\x40\xD6\xB6\xF0\x74\x54\xF5"
>> @@ -260,7 +260,7 @@ static const struct akcipher_testvec rsa_tv_template[] = {
>> #endif
>> .key =
>> "\x30\x82\x02\x20" /* sequence of 544 bytes */
>> - "\x02\x01\x01" /* version - integer of 1 byte */
>> + "\x02\x01\x00" /* version - integer of 1 byte */
>> "\x02\x82\x01\x01\x00" /* modulus - integer of 256 bytes */
>> "\xDB\x10\x1A\xC2\xA3\xF1\xDC\xFF\x13\x6B\xED\x44\xDF\xF0\x02\x6D"
>> "\x13\xC7\x88\xDA\x70\x6B\x54\xF1\xE8\x27\xDC\xC3\x0F\x99\x6A\xFA"
>> --
>> 2.20.1
>