<div dir="ltr">this patch has been test in my env, it look okay for me.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Jul 9, 2020 at 4:42 PM Tianjia Zhang <<a href="mailto:tianjia.zhang@linux.alibaba.com">tianjia.zhang@linux.alibaba.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">This new module implement the SM2 public key algorithm. It was<br>
published by State Encryption Management Bureau, China.<br>
List of specifications for SM2 elliptic curve public key cryptography:<br>
<br>
* GM/T 0003.1-2012<br>
* GM/T 0003.2-2012<br>
* GM/T 0003.3-2012<br>
* GM/T 0003.4-2012<br>
* GM/T 0003.5-2012<br>
<br>
IETF: <a href="https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02" rel="noreferrer" target="_blank">https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02</a><br>
oscca: <a href="http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml" rel="noreferrer" target="_blank">http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml</a><br>
scctc: <a href="http://www.gmbz.org.cn/main/bzlb.html" rel="noreferrer" target="_blank">http://www.gmbz.org.cn/main/bzlb.html</a><br>
<br>
Signed-off-by: Tianjia Zhang <<a href="mailto:tianjia.zhang@linux.alibaba.com" target="_blank">tianjia.zhang@linux.alibaba.com</a>><br>
---<br>
crypto/Kconfig | 17 ++<br>
crypto/Makefile | 8 +<br>
crypto/sm2.c | 473 +++++++++++++++++++++++++++++++++++++++<br>
crypto/sm2signature.asn1 | 4 +<br>
include/crypto/sm2.h | 25 +++<br>
5 files changed, 527 insertions(+)<br>
create mode 100644 crypto/sm2.c<br>
create mode 100644 crypto/sm2signature.asn1<br>
create mode 100644 include/crypto/sm2.h<br>
<br>
diff --git a/crypto/Kconfig b/crypto/Kconfig<br>
index 091c0a0bbf26..de330d658758 100644<br>
--- a/crypto/Kconfig<br>
+++ b/crypto/Kconfig<br>
@@ -260,6 +260,23 @@ config CRYPTO_ECRDSA<br>
standard algorithms (called GOST algorithms). Only signature verification<br>
is implemented.<br>
<br>
+config CRYPTO_SM2<br>
+ tristate "SM2 algorithm"<br>
+ select CRYPTO_SM3<br>
+ select CRYPTO_AKCIPHER<br>
+ select CRYPTO_MANAGER<br>
+ select MPILIB<br>
+ select ASN1<br>
+ help<br>
+ Generic implementation of the SM2 public key algorithm. It was<br>
+ published by State Encryption Management Bureau, China.<br>
+ as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012.<br>
+<br>
+ References:<br>
+ <a href="https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02" rel="noreferrer" target="_blank">https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02</a><br>
+ <a href="http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml" rel="noreferrer" target="_blank">http://www.oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml</a><br>
+ <a href="http://www.gmbz.org.cn/main/bzlb.html" rel="noreferrer" target="_blank">http://www.gmbz.org.cn/main/bzlb.html</a><br>
+<br>
config CRYPTO_CURVE25519<br>
tristate "Curve25519 algorithm"<br>
select CRYPTO_KPP<br>
diff --git a/crypto/Makefile b/crypto/Makefile<br>
index 4ca12b6044f7..b279483fba50 100644<br>
--- a/crypto/Makefile<br>
+++ b/crypto/Makefile<br>
@@ -42,6 +42,14 @@ rsa_generic-y += rsa_helper.o<br>
rsa_generic-y += rsa-pkcs1pad.o<br>
obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o<br>
<br>
+$(obj)/sm2signature.asn1.o: $(obj)/sm2signature.asn1.c $(obj)/sm2signature.asn1.h<br>
+$(obj)/sm2.o: $(obj)/sm2signature.asn1.h<br>
+<br>
+sm2_generic-y += sm2signature.asn1.o<br>
+sm2_generic-y += sm2.o<br>
+<br>
+obj-$(CONFIG_CRYPTO_SM2) += sm2_generic.o<br>
+<br>
crypto_acompress-y := acompress.o<br>
crypto_acompress-y += scompress.o<br>
obj-$(CONFIG_CRYPTO_ACOMP2) += crypto_acompress.o<br>
diff --git a/crypto/sm2.c b/crypto/sm2.c<br>
new file mode 100644<br>
index 000000000000..86da175bcda6<br>
--- /dev/null<br>
+++ b/crypto/sm2.c<br>
@@ -0,0 +1,473 @@<br>
+/* SPDX-License-Identifier: GPL-2.0-or-later */<br>
+/*<br>
+ * SM2 asymmetric public-key algorithm<br>
+ * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and<br>
+ * described at <a href="https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02" rel="noreferrer" target="_blank">https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02</a><br>
+ *<br>
+ * Copyright (c) 2020, Alibaba Group.<br>
+ * Authors: Tianjia Zhang <<a href="mailto:tianjia.zhang@linux.alibaba.com" target="_blank">tianjia.zhang@linux.alibaba.com</a>><br>
+ */<br>
+<br>
+#include <linux/module.h><br>
+#include <linux/mpi.h><br>
+#include <crypto/internal/akcipher.h><br>
+#include <crypto/akcipher.h><br>
+#include <crypto/hash.h><br>
+#include <crypto/sm3_base.h><br>
+#include <crypto/rng.h><br>
+#include <crypto/sm2.h><br>
+#include "sm2signature.asn1.h"<br>
+<br>
+#define MPI_NBYTES(m) ((mpi_get_nbits(m) + 7) / 8)<br>
+<br>
+struct ecc_domain_parms {<br>
+ const char *desc; /* Description of the curve. */<br>
+ unsigned int nbits; /* Number of bits. */<br>
+ unsigned int fips:1; /* True if this is a FIPS140-2 approved curve */<br>
+<br>
+ /* The model describing this curve. This is mainly used to select<br>
+ * the group equation.<br>
+ */<br>
+ enum gcry_mpi_ec_models model;<br>
+<br>
+ /* The actual ECC dialect used. This is used for curve specific<br>
+ * optimizations and to select encodings etc.<br>
+ */<br>
+ enum ecc_dialects dialect;<br>
+<br>
+ const char *p; /* The prime defining the field. */<br>
+ const char *a, *b; /* The coefficients. For Twisted Edwards<br>
+ * Curves b is used for d. For Montgomery<br>
+ * Curves (a,b) has ((A-2)/4,B^-1).<br>
+ */<br>
+ const char *n; /* The order of the base point. */<br>
+ const char *g_x, *g_y; /* Base point. */<br>
+ unsigned int h; /* Cofactor. */<br>
+};<br>
+<br>
+static const struct ecc_domain_parms sm2_ecp = {<br>
+ .desc = "sm2p256v1",<br>
+ .nbits = 256,<br>
+ .fips = 0,<br>
+ .model = MPI_EC_WEIERSTRASS,<br>
+ .dialect = ECC_DIALECT_STANDARD,<br>
+ .p = "0xfffffffeffffffffffffffffffffffffffffffff00000000ffffffffffffffff",<br>
+ .a = "0xfffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc",<br>
+ .b = "0x28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93",<br>
+ .n = "0xfffffffeffffffffffffffffffffffff7203df6b21c6052b53bbf40939d54123",<br>
+ .g_x = "0x32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7",<br>
+ .g_y = "0xbc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0",<br>
+ .h = 1<br>
+};<br>
+<br>
+static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec)<br>
+{<br>
+ const struct ecc_domain_parms *ecp = &sm2_ecp;<br>
+ MPI p, a, b;<br>
+ MPI x, y;<br>
+ int rc = -EINVAL;<br>
+<br>
+ p = mpi_scanval(ecp->p);<br>
+ a = mpi_scanval(ecp->a);<br>
+ b = mpi_scanval(ecp->b);<br>
+ if (!p || !a || !b)<br>
+ goto free_p;<br>
+<br>
+ x = mpi_scanval(ecp->g_x);<br>
+ y = mpi_scanval(ecp->g_y);<br>
+ if (!x || !y)<br>
+ goto free;<br>
+<br>
+ /* mpi_ec_setup_elliptic_curve */<br>
+ ec->G = mpi_point_new(0);<br>
+ if (!ec->G)<br>
+ goto free;<br>
+<br>
+ mpi_set(ec->G->x, x);<br>
+ mpi_set(ec->G->y, y);<br>
+ mpi_set_ui(ec->G->z, 1);<br>
+<br>
+ ec->n = mpi_scanval(ecp->n);<br>
+ if (!ec->n) {<br>
+ mpi_point_release(ec->G);<br>
+ goto free;<br>
+ }<br>
+<br>
+ ec->h = ecp->h;<br>
+ ec->name = ecp->desc;<br>
+ mpi_ec_init(ec, ecp->model, ecp->dialect, 0, p, a, b);<br>
+<br>
+ rc = 0;<br>
+<br>
+free:<br>
+ mpi_free(x);<br>
+ mpi_free(y);<br>
+free_p:<br>
+ mpi_free(p);<br>
+ mpi_free(a);<br>
+ mpi_free(b);<br>
+<br>
+ return rc;<br>
+}<br>
+<br>
+static void sm2_ec_ctx_deinit(struct mpi_ec_ctx *ec)<br>
+{<br>
+ mpi_free(ec->n);<br>
+ mpi_point_release(ec->G);<br>
+<br>
+ mpi_ec_deinit(ec);<br>
+<br>
+ memset(ec, 0, sizeof(*ec));<br>
+}<br>
+<br>
+static int sm2_ec_ctx_reset(struct mpi_ec_ctx *ec)<br>
+{<br>
+ sm2_ec_ctx_deinit(ec);<br>
+ return sm2_ec_ctx_init(ec);<br>
+}<br>
+<br>
+/* RESULT must have been initialized and is set on success to the<br>
+ * point given by VALUE.<br>
+ */<br>
+static int sm2_ecc_os2ec(MPI_POINT result, MPI value)<br>
+{<br>
+ int rc;<br>
+ size_t n;<br>
+ const unsigned char *buf;<br>
+ unsigned char *buf_memory;<br>
+ MPI x, y;<br>
+<br>
+ n = (mpi_get_nbits(value)+7)/8;<br>
+ buf_memory = kmalloc(n, GFP_KERNEL);<br>
+ rc = mpi_print(GCRYMPI_FMT_USG, buf_memory, n, &n, value);<br>
+ if (rc) {<br>
+ kfree(buf_memory);<br>
+ return rc;<br>
+ }<br>
+ buf = buf_memory;<br>
+<br>
+ if (n < 1) {<br>
+ kfree(buf_memory);<br>
+ return -EINVAL;<br>
+ }<br>
+ if (*buf != 4) {<br>
+ kfree(buf_memory);<br>
+ return -EINVAL; /* No support for point compression. */<br>
+ }<br>
+ if (((n-1)%2)) {<br>
+ kfree(buf_memory);<br>
+ return -EINVAL;<br>
+ }<br>
+ n = (n-1)/2;<br>
+ x = mpi_read_raw_data(buf + 1, n);<br>
+ if (!x) {<br>
+ kfree(buf_memory);<br>
+ return -ENOMEM;<br>
+ }<br>
+ y = mpi_read_raw_data(buf + 1 + n, n);<br>
+ kfree(buf_memory);<br>
+ if (!y) {<br>
+ mpi_free(x);<br>
+ return -ENOMEM;<br>
+ }<br>
+<br>
+ mpi_normalize(x);<br>
+ mpi_normalize(y);<br>
+<br>
+ mpi_set(result->x, x);<br>
+ mpi_set(result->y, y);<br>
+ mpi_set_ui(result->z, 1);<br>
+<br>
+ mpi_free(x);<br>
+ mpi_free(y);<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+struct sm2_signature_ctx {<br>
+ MPI sig_r;<br>
+ MPI sig_s;<br>
+};<br>
+<br>
+int sm2_get_signature_r(void *context, size_t hdrlen, unsigned char tag,<br>
+ const void *value, size_t vlen)<br>
+{<br>
+ struct sm2_signature_ctx *sig = context;<br>
+<br>
+ if (!value || !vlen)<br>
+ return -EINVAL;<br>
+<br>
+ sig->sig_r = mpi_read_raw_data(value, vlen);<br>
+ if (!sig->sig_r)<br>
+ return -ENOMEM;<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+int sm2_get_signature_s(void *context, size_t hdrlen, unsigned char tag,<br>
+ const void *value, size_t vlen)<br>
+{<br>
+ struct sm2_signature_ctx *sig = context;<br>
+<br>
+ if (!value || !vlen)<br>
+ return -EINVAL;<br>
+<br>
+ sig->sig_s = mpi_read_raw_data(value, vlen);<br>
+ if (!sig->sig_s)<br>
+ return -ENOMEM;<br>
+<br>
+ return 0;<br>
+}<br>
+<br>
+static int sm2_z_digest_update(struct shash_desc *desc,<br>
+ MPI m, unsigned int pbytes)<br>
+{<br>
+ static const unsigned char zero[32];<br>
+ unsigned char *in;<br>
+ unsigned int inlen;<br>
+<br>
+ in = mpi_get_buffer(m, &inlen, NULL);<br>
+ if (!in)<br>
+ return -EINVAL;<br>
+<br>
+ if (inlen < pbytes) {<br>
+ /* padding with zero */<br>
+ crypto_sm3_update(desc, zero, pbytes - inlen);<br>
+ crypto_sm3_update(desc, in, inlen);<br>
+ } else if (inlen > pbytes) {<br>
+ /* skip the starting zero */<br>
+ crypto_sm3_update(desc, in + inlen - pbytes, pbytes);<br>
+ } else {<br>
+ crypto_sm3_update(desc, in, inlen);<br>
+ }<br>
+<br>
+ kfree(in);<br>
+ return 0;<br>
+}<br>
+<br>
+static int sm2_z_digest_update_point(struct shash_desc *desc,<br>
+ MPI_POINT point, struct mpi_ec_ctx *ec, unsigned int pbytes)<br>
+{<br>
+ MPI x, y;<br>
+ int ret = -EINVAL;<br>
+<br>
+ x = mpi_new(0);<br>
+ y = mpi_new(0);<br>
+<br>
+ if (!mpi_ec_get_affine(x, y, point, ec) &&<br>
+ !sm2_z_digest_update(desc, x, pbytes) &&<br>
+ !sm2_z_digest_update(desc, y, pbytes))<br>
+ ret = 0;<br>
+<br>
+ mpi_free(x);<br>
+ mpi_free(y);<br>
+ return ret;<br>
+}<br>
+<br>
+int sm2_compute_z_digest(struct crypto_akcipher *tfm,<br>
+ const unsigned char *id, size_t id_len,<br>
+ unsigned char dgst[SM3_DIGEST_SIZE])<br>
+{<br>
+ struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);<br>
+ uint16_t bits_len;<br>
+ unsigned char entl[2];<br>
+ SHASH_DESC_ON_STACK(desc, NULL);<br>
+ unsigned int pbytes;<br>
+<br>
+ if (id_len > (USHRT_MAX / 8) || !ec->Q)<br>
+ return -EINVAL;<br>
+<br>
+ bits_len = (uint16_t)(id_len * 8);<br>
+ entl[0] = bits_len >> 8;<br>
+ entl[1] = bits_len & 0xff;<br>
+<br>
+ pbytes = MPI_NBYTES(ec->p);<br>
+<br>
+ /* ZA = H256(ENTLA | IDA | a | b | xG | yG | xA | yA) */<br>
+ sm3_base_init(desc);<br>
+ crypto_sm3_update(desc, entl, 2);<br>
+ crypto_sm3_update(desc, id, id_len);<br>
+<br>
+ if (sm2_z_digest_update(desc, ec->a, pbytes) ||<br>
+ sm2_z_digest_update(desc, ec->b, pbytes) ||<br>
+ sm2_z_digest_update_point(desc, ec->G, ec, pbytes) ||<br>
+ sm2_z_digest_update_point(desc, ec->Q, ec, pbytes))<br>
+ return -EINVAL;<br>
+<br>
+ crypto_sm3_finup(desc, NULL, 0, dgst);<br>
+ return 0;<br>
+}<br>
+EXPORT_SYMBOL(sm2_compute_z_digest);<br>
+<br>
+static int _sm2_verify(struct mpi_ec_ctx *ec, MPI hash, MPI sig_r, MPI sig_s)<br>
+{<br>
+ int rc = -EINVAL;<br>
+ struct gcry_mpi_point sG, tP;<br>
+ MPI t = NULL;<br>
+ MPI x1 = NULL, y1 = NULL;<br>
+<br>
+ mpi_point_init(&sG);<br>
+ mpi_point_init(&tP);<br>
+ x1 = mpi_new(0);<br>
+ y1 = mpi_new(0);<br>
+ t = mpi_new(0);<br>
+<br>
+ /* r, s in [1, n-1] */<br>
+ if (mpi_cmp_ui(sig_r, 1) < 0 || mpi_cmp(sig_r, ec->n) > 0 ||<br>
+ mpi_cmp_ui(sig_s, 1) < 0 || mpi_cmp(sig_s, ec->n) > 0) {<br>
+ goto leave;<br>
+ }<br>
+<br>
+ /* t = (r + s) % n, t == 0 */<br>
+ mpi_addm(t, sig_r, sig_s, ec->n);<br>
+ if (mpi_cmp_ui(t, 0) == 0)<br>
+ goto leave;<br>
+<br>
+ /* sG + tP = (x1, y1) */<br>
+ rc = -EBADMSG;<br>
+ mpi_ec_mul_point(&sG, sig_s, ec->G, ec);<br>
+ mpi_ec_mul_point(&tP, t, ec->Q, ec);<br>
+ mpi_ec_add_points(&sG, &sG, &tP, ec);<br>
+ if (mpi_ec_get_affine(x1, y1, &sG, ec))<br>
+ goto leave;<br>
+<br>
+ /* R = (e + x1) % n */<br>
+ mpi_addm(t, hash, x1, ec->n);<br>
+<br>
+ /* check R == r */<br>
+ rc = -EKEYREJECTED;<br>
+ if (mpi_cmp(t, sig_r))<br>
+ goto leave;<br>
+<br>
+ rc = 0;<br>
+<br>
+leave:<br>
+ mpi_point_free_parts(&sG);<br>
+ mpi_point_free_parts(&tP);<br>
+ mpi_free(x1);<br>
+ mpi_free(y1);<br>
+ mpi_free(t);<br>
+<br>
+ return rc;<br>
+}<br>
+<br>
+static int sm2_verify(struct akcipher_request *req)<br>
+{<br>
+ struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);<br>
+ struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);<br>
+ unsigned char *buffer;<br>
+ struct sm2_signature_ctx sig;<br>
+ MPI hash;<br>
+ int ret;<br>
+<br>
+ if (unlikely(!ec->Q))<br>
+ return -EINVAL;<br>
+<br>
+ buffer = kmalloc(req->src_len + req->dst_len, GFP_KERNEL);<br>
+ if (!buffer)<br>
+ return -ENOMEM;<br>
+<br>
+ sg_pcopy_to_buffer(req->src,<br>
+ sg_nents_for_len(req->src, req->src_len + req->dst_len),<br>
+ buffer, req->src_len + req->dst_len, 0);<br>
+<br>
+ sig.sig_r = NULL;<br>
+ sig.sig_s = NULL;<br>
+ ret = asn1_ber_decoder(&sm2signature_decoder, &sig, buffer, req->src_len);<br>
+ if (ret)<br>
+ goto error;<br>
+<br>
+ ret = -ENOMEM;<br>
+ hash = mpi_read_raw_data(buffer + req->src_len, req->dst_len);<br>
+ if (!hash)<br>
+ goto error;<br>
+<br>
+ ret = _sm2_verify(ec, hash, sig.sig_r, sig.sig_s);<br>
+<br>
+ mpi_free(hash);<br>
+error:<br>
+ mpi_free(sig.sig_r);<br>
+ mpi_free(sig.sig_s);<br>
+ kfree(buffer);<br>
+ return ret;<br>
+}<br>
+<br>
+static int sm2_set_pub_key(struct crypto_akcipher *tfm, const void *key,<br>
+ unsigned int keylen)<br>
+{<br>
+ struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);<br>
+ MPI a;<br>
+ int rc;<br>
+<br>
+ rc = sm2_ec_ctx_reset(ec);<br>
+ if (rc)<br>
+ return rc;<br>
+<br>
+ ec->Q = mpi_point_new(0);<br>
+ if (!ec->Q)<br>
+ return -ENOMEM;<br>
+<br>
+ /* include the uncompressed flag '0x04' */<br>
+ rc = -ENOMEM;<br>
+ a = mpi_read_raw_data(key, keylen);<br>
+ if (!a)<br>
+ goto error;<br>
+<br>
+ mpi_normalize(a);<br>
+ rc = sm2_ecc_os2ec(ec->Q, a);<br>
+ mpi_free(a);<br>
+ if (rc)<br>
+ goto error;<br>
+<br>
+ return 0;<br>
+<br>
+error:<br>
+ mpi_point_release(ec->Q);<br>
+ ec->Q = NULL;<br>
+ return rc;<br>
+}<br>
+<br>
+static unsigned int sm2_max_size(struct crypto_akcipher *tfm)<br>
+{<br>
+ /* Unlimited max size */<br>
+ return PAGE_SIZE;<br>
+}<br>
+<br>
+static void sm2_exit_tfm(struct crypto_akcipher *tfm)<br>
+{<br>
+ struct mpi_ec_ctx *ec = akcipher_tfm_ctx(tfm);<br>
+<br>
+ mpi_ec_deinit(ec);<br>
+}<br>
+<br>
+static struct akcipher_alg sm2 = {<br>
+ .verify = sm2_verify,<br>
+ .set_pub_key = sm2_set_pub_key,<br>
+ .max_size = sm2_max_size,<br>
+ .exit = sm2_exit_tfm,<br>
+ .base = {<br>
+ .cra_name = "sm2",<br>
+ .cra_driver_name = "sm2-generic",<br>
+ .cra_priority = 100,<br>
+ .cra_module = THIS_MODULE,<br>
+ .cra_ctxsize = sizeof(struct mpi_ec_ctx),<br>
+ },<br>
+};<br>
+<br>
+static int sm2_init(void)<br>
+{<br>
+ return crypto_register_akcipher(&sm2);<br>
+}<br>
+<br>
+static void sm2_exit(void)<br>
+{<br>
+ crypto_unregister_akcipher(&sm2);<br>
+}<br>
+<br>
+subsys_initcall(sm2_init);<br>
+module_exit(sm2_exit);<br>
+<br>
+MODULE_LICENSE("GPL");<br>
+MODULE_AUTHOR("Tianjia Zhang <<a href="mailto:tianjia.zhang@linux.alibaba.com" target="_blank">tianjia.zhang@linux.alibaba.com</a>>");<br>
+MODULE_DESCRIPTION("SM2 generic algorithm");<br>
+MODULE_ALIAS_CRYPTO("sm2-generic");<br>
diff --git a/crypto/sm2signature.asn1 b/crypto/sm2signature.asn1<br>
new file mode 100644<br>
index 000000000000..ab8c0b754d21<br>
--- /dev/null<br>
+++ b/crypto/sm2signature.asn1<br>
@@ -0,0 +1,4 @@<br>
+Sm2Signature ::= SEQUENCE {<br>
+ sig_r INTEGER ({ sm2_get_signature_r }),<br>
+ sig_s INTEGER ({ sm2_get_signature_s })<br>
+}<br>
diff --git a/include/crypto/sm2.h b/include/crypto/sm2.h<br>
new file mode 100644<br>
index 000000000000..af452556dcd4<br>
--- /dev/null<br>
+++ b/include/crypto/sm2.h<br>
@@ -0,0 +1,25 @@<br>
+/* SPDX-License-Identifier: GPL-2.0-or-later */<br>
+/*<br>
+ * sm2.h - SM2 asymmetric public-key algorithm<br>
+ * as specified by OSCCA GM/T 0003.1-2012 -- 0003.5-2012 SM2 and<br>
+ * described at <a href="https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02" rel="noreferrer" target="_blank">https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02</a><br>
+ *<br>
+ * Copyright (c) 2020, Alibaba Group.<br>
+ * Written by Tianjia Zhang <<a href="mailto:tianjia.zhang@linux.alibaba.com" target="_blank">tianjia.zhang@linux.alibaba.com</a>><br>
+ */<br>
+<br>
+#ifndef _CRYPTO_SM2_H<br>
+#define _CRYPTO_SM2_H<br>
+<br>
+#include <crypto/sm3.h><br>
+#include <crypto/akcipher.h><br>
+<br>
+/* The default user id as specified in GM/T 0009-2012 */<br>
+#define SM2_DEFAULT_USERID "1234567812345678"<br>
+#define SM2_DEFAULT_USERID_LEN 16<br>
+<br>
+extern int sm2_compute_z_digest(struct crypto_akcipher *tfm,<br>
+ const unsigned char *id, size_t id_len,<br>
+ unsigned char dgst[SM3_DIGEST_SIZE]);<br>
+<br>
+#endif /* _CRYPTO_SM2_H */<br>
-- <br>
2.17.1<br>
<br>
</blockquote></div>