xref: /openbsd-src/lib/libcrypto/sm2/sm2_sign.c (revision 6ddee6b2f030ff630644d554ad4ace301b323344)
1*6ddee6b2Stb /*	$OpenBSD: sm2_sign.c,v 1.4 2023/07/05 17:36:19 tb Exp $ */
251892d90Stb /*
351892d90Stb  * Copyright (c) 2017, 2019 Ribose Inc
451892d90Stb  *
551892d90Stb  * Permission to use, copy, modify, and/or distribute this software for any
651892d90Stb  * purpose with or without fee is hereby granted, provided that the above
751892d90Stb  * copyright notice and this permission notice appear in all copies.
851892d90Stb  *
951892d90Stb  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1051892d90Stb  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1151892d90Stb  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1251892d90Stb  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1351892d90Stb  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1451892d90Stb  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1551892d90Stb  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1651892d90Stb  */
1751892d90Stb 
1851892d90Stb #ifndef OPENSSL_NO_SM2
1951892d90Stb 
2051892d90Stb #include <string.h>
2151892d90Stb 
2251892d90Stb #include <openssl/sm2.h>
2351892d90Stb #include <openssl/evp.h>
2451892d90Stb #include <openssl/err.h>
2551892d90Stb #include <openssl/bn.h>
2651892d90Stb 
27c9675a23Stb #include "bn_local.h"
28c9675a23Stb #include "sm2_local.h"
2951892d90Stb 
3051892d90Stb static BIGNUM *
sm2_compute_msg_hash(const EVP_MD * digest,const EC_KEY * key,const uint8_t * uid,size_t uid_len,const uint8_t * msg,size_t msg_len)3151892d90Stb sm2_compute_msg_hash(const EVP_MD *digest, const EC_KEY *key,
3251892d90Stb     const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len)
3351892d90Stb {
3451892d90Stb 	EVP_MD_CTX *hash;
3551892d90Stb 	BIGNUM *e = NULL;
3651892d90Stb 	int md_size;
3751892d90Stb 	uint8_t *za = NULL;
3851892d90Stb 
3951892d90Stb 	if ((hash = EVP_MD_CTX_new()) == NULL) {
4051892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
4151892d90Stb 		goto err;
4251892d90Stb 	}
4351892d90Stb 
4451892d90Stb 	if ((md_size = EVP_MD_size(digest)) < 0) {
4551892d90Stb 		SM2error(SM2_R_INVALID_DIGEST);
4651892d90Stb 		goto err;
4751892d90Stb 	}
4851892d90Stb 
4951892d90Stb 	if ((za = calloc(1, md_size)) == NULL) {
5051892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
5151892d90Stb 		goto err;
5251892d90Stb 	}
5351892d90Stb 
5451892d90Stb 	if (!sm2_compute_userid_digest(za, digest, uid, uid_len, key)) {
5551892d90Stb 		SM2error(SM2_R_DIGEST_FAILURE);
5651892d90Stb 		goto err;
5751892d90Stb 	}
5851892d90Stb 
5951892d90Stb 	if (!EVP_DigestInit(hash, digest)) {
6051892d90Stb 		SM2error(ERR_R_EVP_LIB);
6151892d90Stb 		goto err;
6251892d90Stb 	}
6351892d90Stb 
6451892d90Stb 	if (!EVP_DigestUpdate(hash, za, md_size)) {
6551892d90Stb 		SM2error(ERR_R_EVP_LIB);
6651892d90Stb 		goto err;
6751892d90Stb 	}
6851892d90Stb 
6951892d90Stb 	if (!EVP_DigestUpdate(hash, msg, msg_len)) {
7051892d90Stb 		SM2error(ERR_R_EVP_LIB);
7151892d90Stb 		goto err;
7251892d90Stb 	}
7351892d90Stb 
7451892d90Stb 	/* reuse za buffer to hold H(ZA || M) */
7551892d90Stb 	if (!EVP_DigestFinal(hash, za, NULL)) {
7651892d90Stb 		SM2error(ERR_R_EVP_LIB);
7751892d90Stb 		goto err;
7851892d90Stb 	}
7951892d90Stb 
8051892d90Stb 	e = BN_bin2bn(za, md_size, NULL);
8151892d90Stb 
8251892d90Stb  err:
8351892d90Stb 	free(za);
8451892d90Stb 	EVP_MD_CTX_free(hash);
8551892d90Stb 	return e;
8651892d90Stb }
8751892d90Stb 
8851892d90Stb static ECDSA_SIG *
sm2_sig_gen(const EC_KEY * key,const BIGNUM * e)8951892d90Stb sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
9051892d90Stb {
9151892d90Stb 	ECDSA_SIG *sig = NULL;
9251892d90Stb 	const EC_GROUP *group;
9351892d90Stb 	EC_POINT *kG = NULL;
9451892d90Stb 	BN_CTX *ctx = NULL;
9551892d90Stb 	const BIGNUM *dA;
9651892d90Stb 	BIGNUM *order = NULL, *r = NULL, *s = NULL;
9751892d90Stb 	BIGNUM *k, *rk, *tmp, *x1;
9851892d90Stb 
9951892d90Stb 	if ((dA = EC_KEY_get0_private_key(key)) == NULL) {
10051892d90Stb 		SM2error(SM2_R_INVALID_FIELD);
10151892d90Stb 		goto err;
10251892d90Stb 	}
10351892d90Stb 
10451892d90Stb 	if ((group = EC_KEY_get0_group(key)) == NULL) {
10551892d90Stb 		SM2error(SM2_R_INVALID_FIELD);
10651892d90Stb 		goto err;
10751892d90Stb 	}
10851892d90Stb 
10951892d90Stb 	if ((order = BN_new()) == NULL) {
11051892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
11151892d90Stb 		goto err;
11251892d90Stb 	}
11351892d90Stb 
11451892d90Stb 	if (!EC_GROUP_get_order(group, order, NULL)) {
11551892d90Stb 		SM2error(ERR_R_EC_LIB);
11651892d90Stb 		goto err;
11751892d90Stb 	}
11851892d90Stb 
11951892d90Stb 	if ((kG = EC_POINT_new(group)) == NULL) {
12051892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
12151892d90Stb 		goto err;
12251892d90Stb 	}
12351892d90Stb 
12451892d90Stb 	if ((ctx = BN_CTX_new()) == NULL) {
12551892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
12651892d90Stb 		goto err;
12751892d90Stb 	}
12851892d90Stb 
12951892d90Stb 	BN_CTX_start(ctx);
13051892d90Stb 
13151892d90Stb 	if ((k = BN_CTX_get(ctx)) == NULL) {
13251892d90Stb 		SM2error(ERR_R_BN_LIB);
13351892d90Stb 		goto err;
13451892d90Stb 	}
13551892d90Stb 	if ((rk = BN_CTX_get(ctx)) == NULL) {
13651892d90Stb 		SM2error(ERR_R_BN_LIB);
13751892d90Stb 		goto err;
13851892d90Stb 	}
13951892d90Stb 	if ((x1 = BN_CTX_get(ctx)) == NULL) {
14051892d90Stb 		SM2error(ERR_R_BN_LIB);
14151892d90Stb 		goto err;
14251892d90Stb 	}
14351892d90Stb 	if ((tmp = BN_CTX_get(ctx)) == NULL) {
14451892d90Stb 		SM2error(ERR_R_BN_LIB);
14551892d90Stb 		goto err;
14651892d90Stb 	}
14751892d90Stb 
14851892d90Stb 	/* r and s are returned as part of sig, so they can't be part of ctx. */
14951892d90Stb 	if ((r = BN_new()) == NULL) {
15051892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
15151892d90Stb 		goto err;
15251892d90Stb 	}
15351892d90Stb 	if ((s = BN_new()) == NULL) {
15451892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
15551892d90Stb 		goto err;
15651892d90Stb 	}
15751892d90Stb 
15851892d90Stb 	for (;;) {
15951892d90Stb 		if (!BN_rand_range(k, order)) {
16051892d90Stb 			SM2error(SM2_R_RANDOM_NUMBER_GENERATION_FAILED);
16151892d90Stb 			goto err;
16251892d90Stb 		}
16351892d90Stb 
16451892d90Stb 		if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)) {
16551892d90Stb 			SM2error(ERR_R_EC_LIB);
16651892d90Stb 			goto err;
16751892d90Stb 		}
16851892d90Stb 
16951892d90Stb 		if (!EC_POINT_get_affine_coordinates(group, kG, x1, NULL,
17051892d90Stb 		    ctx)) {
17151892d90Stb 			SM2error(ERR_R_EC_LIB);
17251892d90Stb 			goto err;
17351892d90Stb 		}
17451892d90Stb 
17551892d90Stb 		if (!BN_mod_add(r, e, x1, order, ctx)) {
17651892d90Stb 			SM2error(ERR_R_BN_LIB);
17751892d90Stb 			goto err;
17851892d90Stb 		}
17951892d90Stb 
18051892d90Stb 		/* try again if r == 0 or r + k == n */
18151892d90Stb 		if (BN_is_zero(r))
18251892d90Stb 			continue;
18351892d90Stb 
18451892d90Stb 		if (!BN_add(rk, r, k)) {
18551892d90Stb 			SM2error(ERR_R_BN_LIB);
18651892d90Stb 			goto err;
18751892d90Stb 		}
18851892d90Stb 
18951892d90Stb 		if (BN_cmp(rk, order) == 0)
19051892d90Stb 			continue;
19151892d90Stb 
19251892d90Stb 		if (!BN_add(s, dA, BN_value_one())) {
19351892d90Stb 			SM2error(ERR_R_BN_LIB);
19451892d90Stb 			goto err;
19551892d90Stb 		}
19651892d90Stb 
197cb26bec3Sinoguchi 		if (BN_mod_inverse_ct(s, s, order, ctx) == NULL) {
19851892d90Stb 			SM2error(ERR_R_BN_LIB);
19951892d90Stb 			goto err;
20051892d90Stb 		}
20151892d90Stb 
20251892d90Stb 		if (!BN_mod_mul(tmp, dA, r, order, ctx)) {
20351892d90Stb 			SM2error(ERR_R_BN_LIB);
20451892d90Stb 			goto err;
20551892d90Stb 		}
20651892d90Stb 
20751892d90Stb 		if (!BN_sub(tmp, k, tmp)) {
20851892d90Stb 			SM2error(ERR_R_BN_LIB);
20951892d90Stb 			goto err;
21051892d90Stb 		}
21151892d90Stb 
21251892d90Stb 		if (!BN_mod_mul(s, s, tmp, order, ctx)) {
21351892d90Stb 			SM2error(ERR_R_BN_LIB);
21451892d90Stb 			goto err;
21551892d90Stb 		}
21651892d90Stb 
21751892d90Stb 		if ((sig = ECDSA_SIG_new()) == NULL) {
21851892d90Stb 			SM2error(ERR_R_MALLOC_FAILURE);
21951892d90Stb 			goto err;
22051892d90Stb 		}
22151892d90Stb 
22251892d90Stb 		/* sig takes ownership of r and s */
22351892d90Stb 		if (!ECDSA_SIG_set0(sig, r, s)) {
22451892d90Stb 			SM2error(ERR_R_INTERNAL_ERROR);
22551892d90Stb 			goto err;
22651892d90Stb 		}
22751892d90Stb 		break;
22851892d90Stb 	}
22951892d90Stb 
23051892d90Stb  err:
23151892d90Stb 	if (sig == NULL) {
23251892d90Stb 		BN_free(r);
23351892d90Stb 		BN_free(s);
23451892d90Stb 	}
23551892d90Stb 
23651892d90Stb 	BN_free(order);
23751892d90Stb 	BN_CTX_end(ctx);
23851892d90Stb 	BN_CTX_free(ctx);
23951892d90Stb 	EC_POINT_free(kG);
24051892d90Stb 	return sig;
24151892d90Stb }
24251892d90Stb 
24351892d90Stb static int
sm2_sig_verify(const EC_KEY * key,const ECDSA_SIG * sig,const BIGNUM * e)24451892d90Stb sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig, const BIGNUM *e)
24551892d90Stb {
24651892d90Stb 	const EC_GROUP *group;
24751892d90Stb 	EC_POINT *pt = NULL;
24851892d90Stb 	const BIGNUM *r = NULL, *s = NULL;
24951892d90Stb 	BN_CTX *ctx = NULL;
25051892d90Stb 	BIGNUM *order, *t, *x1;
25151892d90Stb 	int ret = 0;
25251892d90Stb 
25351892d90Stb 	if ((group = EC_KEY_get0_group(key)) == NULL) {
25451892d90Stb 		SM2error(SM2_R_INVALID_FIELD);
25551892d90Stb 		goto err;
25651892d90Stb 	}
25751892d90Stb 
25851892d90Stb 	if ((ctx = BN_CTX_new()) == NULL) {
25951892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
26051892d90Stb 		goto err;
26151892d90Stb 	}
26251892d90Stb 
26351892d90Stb 	BN_CTX_start(ctx);
26451892d90Stb 
26551892d90Stb 	if ((order = BN_CTX_get(ctx)) == NULL) {
26651892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
26751892d90Stb 		goto err;
26851892d90Stb 	}
26951892d90Stb 
27051892d90Stb 	if (!EC_GROUP_get_order(group, order, NULL)) {
27151892d90Stb 		SM2error(ERR_R_EC_LIB);
27251892d90Stb 		goto err;
27351892d90Stb 	}
27451892d90Stb 
27551892d90Stb 	if ((pt = EC_POINT_new(group)) == NULL) {
27651892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
27751892d90Stb 		goto err;
27851892d90Stb 	}
27951892d90Stb 
28051892d90Stb 	if ((t = BN_CTX_get(ctx)) == NULL) {
28151892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
28251892d90Stb 		goto err;
28351892d90Stb 	}
28451892d90Stb 	if ((x1 = BN_CTX_get(ctx)) == NULL) {
28551892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
28651892d90Stb 		goto err;
28751892d90Stb 	}
28851892d90Stb 
28951892d90Stb 	/*
29051892d90Stb 	 * Section 5.3.1 in https://tools.ietf.org/html/draft-shen-sm2-ecdsa-00
29151892d90Stb 	 *
29251892d90Stb 	 * B1: verify that r' is in [1, n-1]
29351892d90Stb 	 * B2: verify that s' is in [1, n-1]
29451892d90Stb 	 * B3: set M' ~= ZA || M'
29551892d90Stb 	 * B4: calculate e' = Hv(M'~)
29651892d90Stb 	 * B5: verify that t = r' + s' (mod n) is not zero
29751892d90Stb 	 * B6: calculate the point (x1', y1') = [s']G + [t]PA
29851892d90Stb 	 * B7: verify that r' == e' + x1' (mod n)
29951892d90Stb 	 */
30051892d90Stb 
30151892d90Stb 	ECDSA_SIG_get0(sig, &r, &s);
30251892d90Stb 
30351892d90Stb 	/* B1: verify that r' is in [1, n-1] */
30451892d90Stb 	if (BN_cmp(r, BN_value_one()) < 0 || BN_cmp(order, r) <= 0) {
30551892d90Stb 		SM2error(SM2_R_BAD_SIGNATURE);
30651892d90Stb 		goto err;
30751892d90Stb 	}
30851892d90Stb 
30951892d90Stb 	/* B2: verify that s' is in [1, n-1] */
31051892d90Stb 	if (BN_cmp(s, BN_value_one()) < 0 || BN_cmp(order, s) <= 0) {
31151892d90Stb 		SM2error(SM2_R_BAD_SIGNATURE);
31251892d90Stb 		goto err;
31351892d90Stb 	}
31451892d90Stb 
31551892d90Stb 	/* B5: verify that t = r + s is not zero */
31651892d90Stb 	if (!BN_mod_add(t, r, s, order, ctx)) {
31751892d90Stb 		SM2error(ERR_R_BN_LIB);
31851892d90Stb 		goto err;
31951892d90Stb 	}
32051892d90Stb 	if (BN_is_zero(t)) {
32151892d90Stb 		SM2error(SM2_R_BAD_SIGNATURE);
32251892d90Stb 		goto err;
32351892d90Stb 	}
32451892d90Stb 
32551892d90Stb 	/* B6: calculate pt = (x1', y1') = [s']G + [t]PA */
32651892d90Stb 	if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)) {
32751892d90Stb 		SM2error(ERR_R_EC_LIB);
32851892d90Stb 		goto err;
32951892d90Stb 	}
33051892d90Stb 
33151892d90Stb 	if (!EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) {
33251892d90Stb 		SM2error(ERR_R_EC_LIB);
33351892d90Stb 		goto err;
33451892d90Stb 	}
33551892d90Stb 
33651892d90Stb 	/* B7: verify that r' == e' + x1' (mod n) */
33751892d90Stb 	if (!BN_mod_add(t, e, x1, order, ctx)) {
33851892d90Stb 		SM2error(ERR_R_BN_LIB);
33951892d90Stb 		goto err;
34051892d90Stb 	}
34151892d90Stb 	if (BN_cmp(r, t) == 0)
34251892d90Stb 		ret = 1;
34351892d90Stb 
34451892d90Stb  err:
34551892d90Stb 	EC_POINT_free(pt);
34651892d90Stb 	BN_CTX_end(ctx);
34751892d90Stb 	BN_CTX_free(ctx);
34851892d90Stb 	return ret;
34951892d90Stb }
35051892d90Stb 
35151892d90Stb ECDSA_SIG *
sm2_do_sign(const EC_KEY * key,const EVP_MD * digest,const uint8_t * uid,size_t uid_len,const uint8_t * msg,size_t msg_len)35251892d90Stb sm2_do_sign(const EC_KEY *key, const EVP_MD *digest, const uint8_t *uid,
35351892d90Stb     size_t uid_len, const uint8_t *msg, size_t msg_len)
35451892d90Stb {
35551892d90Stb 	ECDSA_SIG *sig = NULL;
35651892d90Stb 	BIGNUM *e;
35751892d90Stb 
35851892d90Stb 	e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len);
35951892d90Stb 	if (e == NULL) {
36051892d90Stb 		SM2error(SM2_R_DIGEST_FAILURE);
36151892d90Stb 		goto err;
36251892d90Stb 	}
36351892d90Stb 
36451892d90Stb 	sig = sm2_sig_gen(key, e);
36551892d90Stb 
36651892d90Stb  err:
36751892d90Stb 	BN_free(e);
36851892d90Stb 	return sig;
36951892d90Stb }
37051892d90Stb 
37151892d90Stb int
sm2_do_verify(const EC_KEY * key,const EVP_MD * digest,const ECDSA_SIG * sig,const uint8_t * uid,size_t uid_len,const uint8_t * msg,size_t msg_len)37251892d90Stb sm2_do_verify(const EC_KEY *key, const EVP_MD *digest, const ECDSA_SIG *sig,
37351892d90Stb     const uint8_t *uid, size_t uid_len, const uint8_t *msg, size_t msg_len)
37451892d90Stb {
37551892d90Stb 	BIGNUM *e;
37651892d90Stb 	int ret = -1;
37751892d90Stb 
37851892d90Stb 	e = sm2_compute_msg_hash(digest, key, uid, uid_len, msg, msg_len);
37951892d90Stb 	if (e == NULL) {
38051892d90Stb 		SM2error(SM2_R_DIGEST_FAILURE);
38151892d90Stb 		goto err;
38251892d90Stb 	}
38351892d90Stb 
38451892d90Stb 	ret = sm2_sig_verify(key, sig, e);
38551892d90Stb 
38651892d90Stb  err:
38751892d90Stb 	BN_free(e);
38851892d90Stb 	return ret;
38951892d90Stb }
39051892d90Stb 
39151892d90Stb int
SM2_sign(const unsigned char * dgst,int dgstlen,unsigned char * sig,unsigned int * siglen,EC_KEY * eckey)39251892d90Stb SM2_sign(const unsigned char *dgst, int dgstlen, unsigned char *sig,
39351892d90Stb     unsigned int *siglen, EC_KEY *eckey)
39451892d90Stb {
39551892d90Stb 	BIGNUM *e;
39651892d90Stb 	ECDSA_SIG *s = NULL;
39751892d90Stb 	int outlen = 0;
39851892d90Stb 	int ret = -1;
39951892d90Stb 
40051892d90Stb 	if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) {
40151892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
40251892d90Stb 		goto err;
40351892d90Stb 	}
40451892d90Stb 
40551892d90Stb 	if ((s = sm2_sig_gen(eckey, e)) == NULL) {
40651892d90Stb 		goto err;
40751892d90Stb 	}
40851892d90Stb 
40951892d90Stb 	if ((outlen = i2d_ECDSA_SIG(s, &sig)) < 0) {
41051892d90Stb 		SM2error(SM2_R_ASN1_ERROR);
41151892d90Stb 		goto err;
41251892d90Stb 	}
41351892d90Stb 
41451892d90Stb 	*siglen = outlen;
41551892d90Stb 	ret = 1;
41651892d90Stb 
41751892d90Stb  err:
41851892d90Stb 	ECDSA_SIG_free(s);
41951892d90Stb 	BN_free(e);
42051892d90Stb 	return ret;
42151892d90Stb }
42251892d90Stb 
42351892d90Stb int
SM2_verify(const unsigned char * dgst,int dgstlen,const unsigned char * sig,int sig_len,EC_KEY * eckey)42451892d90Stb SM2_verify(const unsigned char *dgst, int dgstlen, const unsigned char *sig,
42551892d90Stb     int sig_len, EC_KEY *eckey)
42651892d90Stb {
42751892d90Stb 	ECDSA_SIG *s;
42851892d90Stb 	BIGNUM *e = NULL;
42951892d90Stb 	const unsigned char *p = sig;
43051892d90Stb 	unsigned char *der = NULL;
43151892d90Stb 	int derlen = -1;
43251892d90Stb 	int ret = -1;
43351892d90Stb 
43451892d90Stb 	if ((s = ECDSA_SIG_new()) == NULL) {
43551892d90Stb 		SM2error(ERR_R_MALLOC_FAILURE);
43651892d90Stb 		goto err;
43751892d90Stb 	}
43851892d90Stb 
43951892d90Stb 	if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) {
44051892d90Stb 		SM2error(SM2_R_INVALID_ENCODING);
44151892d90Stb 		goto err;
44251892d90Stb 	}
44351892d90Stb 
44451892d90Stb 	/* Ensure signature uses DER and doesn't have trailing garbage */
44551892d90Stb 	derlen = i2d_ECDSA_SIG(s, &der);
44651892d90Stb 	if (derlen != sig_len || memcmp(sig, der, derlen) != 0) {
44751892d90Stb 		SM2error(SM2_R_INVALID_ENCODING);
44851892d90Stb 		goto err;
44951892d90Stb 	}
45051892d90Stb 
45151892d90Stb 	if ((e = BN_bin2bn(dgst, dgstlen, NULL)) == NULL) {
45251892d90Stb 		SM2error(ERR_R_BN_LIB);
45351892d90Stb 		goto err;
45451892d90Stb 	}
45551892d90Stb 
45651892d90Stb 	ret = sm2_sig_verify(eckey, s, e);
45751892d90Stb 
45851892d90Stb  err:
45951892d90Stb 	free(der);
46051892d90Stb 	BN_free(e);
46151892d90Stb 	ECDSA_SIG_free(s);
46251892d90Stb 	return ret;
46351892d90Stb }
46451892d90Stb 
46551892d90Stb #endif /* OPENSSL_NO_SM2 */
466