All of lore.kernel.org
 help / color / mirror / Atom feed
From: Huaxin Lu <luhuaxin1@huawei.com>
To: David Howells <dhowells@redhat.com>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	"David S . Miller" <davem@davemloft.net>,
	<keyrings@vger.kernel.org>, <linux-crypto@vger.kernel.org>
Cc: <xiujianfeng@huawei.com>, <wangweiyang2@huawei.com>,
	<yiyang13@huawei.com>, <zhujianwei7@huawei.com>,
	<shenyining@huawei.com>, <luhuaxin1@huawei.com>
Subject: [PATCH] Move SM2 digest calculation to signature verification
Date: Tue, 14 May 2024 07:07:18 +0800	[thread overview]
Message-ID: <20240513230718.447895-1-luhuaxin1@huawei.com> (raw)

In the commit of e5221fa6a355 ("KEYS: asymmetric: Move sm2 code into
x509_public_key"), the SM2 digest hashing is moved to the process of
certificate loading. It cause the SM2 certificate chain validation
failure. For example, when importing a SM2 IMA certificate (x509_ima.der)
verified by the trusted kering. The import fails due to the wrong Z value
calculating. Because he Z value should be calculated from the public key
of the signing certificate, not from the public key of the certificate
itself (reference: datatracker.ietf.org/doc/html/draft-shen-sm2-ecdsa-02).

This commit partially revert the previous commit. Restore SM2 digest value
calculating into the signature verification process, and use the right
information to calculate Z value and SM2 digest.

Fixes: e5221fa6a355 ("KEYS: asymmetric: Move sm2 code into x509_public_key")
Signed-off-by: Huaxin Lu <luhuaxin1@huawei.com>
---
 crypto/asymmetric_keys/public_key.c      | 57 ++++++++++++++++++++++++
 crypto/asymmetric_keys/x509_public_key.c | 20 +++------
 include/crypto/public_key.h              |  2 +
 3 files changed, 64 insertions(+), 15 deletions(-)

diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c
index e314fd57e..647a03e00 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -9,8 +9,11 @@
 
 #define pr_fmt(fmt) "PKEY: "fmt
 #include <crypto/akcipher.h>
+#include <crypto/hash.h>
 #include <crypto/public_key.h>
 #include <crypto/sig.h>
+#include <crypto/sm2.h>
+#include <crypto/sm3.h>
 #include <keys/asymmetric-subtype.h>
 #include <linux/asn1.h>
 #include <linux/err.h>
@@ -376,6 +379,54 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
 	return ret;
 }
 
+#if IS_REACHABLE(CONFIG_CRYPTO_SM2)
+static int cert_sig_digest_update(const struct public_key_signature *sig,
+				  void *pkey, size_t pkey_len)
+{
+	struct crypto_shash *tfm;
+	struct shash_desc *desc;
+	size_t desc_size;
+	unsigned char dgst[SM3_DIGEST_SIZE];
+	int ret;
+
+	BUG_ON(!sig->data);
+
+	/* SM2 signatures always use the SM3 hash algorithm */
+	if (!sig->hash_algo || strcmp(sig->hash_algo, "sm3") != 0)
+		return -EINVAL;
+
+	tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
+	if (IS_ERR(tfm))
+		return PTR_ERR(tfm);
+
+	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
+	desc = kzalloc(desc_size, GFP_KERNEL);
+	if (!desc) {
+		crypto_free_shash(tfm);
+		return -ENOMEM;
+	}
+
+	desc->tfm = tfm;
+
+	ret = crypto_shash_init(desc) ?:
+	      sm2_compute_z_digest(desc, pkey, pkey_len, dgst) ?:
+	      crypto_shash_init(desc) ?:
+	      crypto_shash_update(desc, dgst, SM3_DIGEST_SIZE) ?:
+	      crypto_shash_finup(desc, sig->data, sig->data_size, sig->digest);
+
+	kfree(desc);
+	crypto_free_shash(tfm);
+	return ret;
+}
+#else
+static inline int cert_sig_digest_update(
+	const struct public_key_signature *sig,
+	void *pkey, size_t pkey_len)
+{
+	return -ENOTSUPP;
+}
+#endif /* ! IS_REACHABLE(CONFIG_CRYPTO_SM2) */
+
 /*
  * Verify a signature using a public key.
  */
@@ -439,6 +490,12 @@ int public_key_verify_signature(const struct public_key *pkey,
 	if (ret)
 		goto error_free_key;
 
+	if (strcmp(pkey->pkey_algo, "sm2") == 0 && sig->data_size) {
+		ret = cert_sig_digest_update(sig, key, pkey->keylen);
+		if (ret)
+			goto error_free_key;
+	}
+
 	ret = crypto_sig_verify(tfm, sig->s, sig->s_size,
 				sig->digest, sig->digest_size);
 
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 6a4f00be2..54738af7d 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -32,6 +32,9 @@ int x509_get_sig_params(struct x509_certificate *cert)
 
 	pr_devel("==>%s()\n", __func__);
 
+	sig->data = cert->tbs;
+	sig->data_size = cert->tbs_size;
+
 	sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
 	if (!sig->s)
 		return -ENOMEM;
@@ -64,21 +67,8 @@ int x509_get_sig_params(struct x509_certificate *cert)
 
 	desc->tfm = tfm;
 
-	if (strcmp(cert->pub->pkey_algo, "sm2") == 0) {
-		ret = strcmp(sig->hash_algo, "sm3") != 0 ? -EINVAL :
-		      crypto_shash_init(desc) ?:
-		      sm2_compute_z_digest(desc, cert->pub->key,
-					   cert->pub->keylen, sig->digest) ?:
-		      crypto_shash_init(desc) ?:
-		      crypto_shash_update(desc, sig->digest,
-					  sig->digest_size) ?:
-		      crypto_shash_finup(desc, cert->tbs, cert->tbs_size,
-					 sig->digest);
-	} else {
-		ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size,
-					  sig->digest);
-	}
-
+	ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size,
+				  sig->digest);
 	if (ret < 0)
 		goto error_2;
 
diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h
index b7f308977..fce68803b 100644
--- a/include/crypto/public_key.h
+++ b/include/crypto/public_key.h
@@ -49,6 +49,8 @@ struct public_key_signature {
 	const char *pkey_algo;
 	const char *hash_algo;
 	const char *encoding;
+	const void *data;
+	unsigned int data_size;
 };
 
 extern void public_key_signature_free(struct public_key_signature *sig);
-- 
2.33.0


             reply	other threads:[~2024-05-14  1:43 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-13 23:07 Huaxin Lu [this message]
2024-05-17 10:46 ` [PATCH] Move SM2 digest calculation to signature verification Herbert Xu

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=20240513230718.447895-1-luhuaxin1@huawei.com \
    --to=luhuaxin1@huawei.com \
    --cc=davem@davemloft.net \
    --cc=dhowells@redhat.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-crypto@vger.kernel.org \
    --cc=shenyining@huawei.com \
    --cc=wangweiyang2@huawei.com \
    --cc=xiujianfeng@huawei.com \
    --cc=yiyang13@huawei.com \
    --cc=zhujianwei7@huawei.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.