xref: /third_party/openssl/crypto/sm2/sm2_sign.c (revision e1051a39)
1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2017-2023 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci * Copyright 2017 Ribose Inc. All Rights Reserved.
4e1051a39Sopenharmony_ci * Ported from Ribose contributions from Botan.
5e1051a39Sopenharmony_ci *
6e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
7e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
8e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
9e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
10e1051a39Sopenharmony_ci */
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_ci#include "internal/deprecated.h"
13e1051a39Sopenharmony_ci
14e1051a39Sopenharmony_ci#include "crypto/sm2.h"
15e1051a39Sopenharmony_ci#include "crypto/sm2err.h"
16e1051a39Sopenharmony_ci#include "crypto/ec.h" /* ossl_ec_group_do_inverse_ord() */
17e1051a39Sopenharmony_ci#include "internal/numbers.h"
18e1051a39Sopenharmony_ci#include <openssl/err.h>
19e1051a39Sopenharmony_ci#include <openssl/evp.h>
20e1051a39Sopenharmony_ci#include <openssl/err.h>
21e1051a39Sopenharmony_ci#include <openssl/bn.h>
22e1051a39Sopenharmony_ci#include <string.h>
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_ciint ossl_sm2_compute_z_digest(uint8_t *out,
25e1051a39Sopenharmony_ci                              const EVP_MD *digest,
26e1051a39Sopenharmony_ci                              const uint8_t *id,
27e1051a39Sopenharmony_ci                              const size_t id_len,
28e1051a39Sopenharmony_ci                              const EC_KEY *key)
29e1051a39Sopenharmony_ci{
30e1051a39Sopenharmony_ci    int rc = 0;
31e1051a39Sopenharmony_ci    const EC_GROUP *group = EC_KEY_get0_group(key);
32e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
33e1051a39Sopenharmony_ci    EVP_MD_CTX *hash = NULL;
34e1051a39Sopenharmony_ci    BIGNUM *p = NULL;
35e1051a39Sopenharmony_ci    BIGNUM *a = NULL;
36e1051a39Sopenharmony_ci    BIGNUM *b = NULL;
37e1051a39Sopenharmony_ci    BIGNUM *xG = NULL;
38e1051a39Sopenharmony_ci    BIGNUM *yG = NULL;
39e1051a39Sopenharmony_ci    BIGNUM *xA = NULL;
40e1051a39Sopenharmony_ci    BIGNUM *yA = NULL;
41e1051a39Sopenharmony_ci    int p_bytes = 0;
42e1051a39Sopenharmony_ci    uint8_t *buf = NULL;
43e1051a39Sopenharmony_ci    uint16_t entl = 0;
44e1051a39Sopenharmony_ci    uint8_t e_byte = 0;
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci    hash = EVP_MD_CTX_new();
47e1051a39Sopenharmony_ci    ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(key));
48e1051a39Sopenharmony_ci    if (hash == NULL || ctx == NULL) {
49e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
50e1051a39Sopenharmony_ci        goto done;
51e1051a39Sopenharmony_ci    }
52e1051a39Sopenharmony_ci
53e1051a39Sopenharmony_ci    p = BN_CTX_get(ctx);
54e1051a39Sopenharmony_ci    a = BN_CTX_get(ctx);
55e1051a39Sopenharmony_ci    b = BN_CTX_get(ctx);
56e1051a39Sopenharmony_ci    xG = BN_CTX_get(ctx);
57e1051a39Sopenharmony_ci    yG = BN_CTX_get(ctx);
58e1051a39Sopenharmony_ci    xA = BN_CTX_get(ctx);
59e1051a39Sopenharmony_ci    yA = BN_CTX_get(ctx);
60e1051a39Sopenharmony_ci
61e1051a39Sopenharmony_ci    if (yA == NULL) {
62e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
63e1051a39Sopenharmony_ci        goto done;
64e1051a39Sopenharmony_ci    }
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci    if (!EVP_DigestInit(hash, digest)) {
67e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
68e1051a39Sopenharmony_ci        goto done;
69e1051a39Sopenharmony_ci    }
70e1051a39Sopenharmony_ci
71e1051a39Sopenharmony_ci    /* Z = h(ENTL || ID || a || b || xG || yG || xA || yA) */
72e1051a39Sopenharmony_ci
73e1051a39Sopenharmony_ci    if (id_len >= (UINT16_MAX / 8)) {
74e1051a39Sopenharmony_ci        /* too large */
75e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, SM2_R_ID_TOO_LARGE);
76e1051a39Sopenharmony_ci        goto done;
77e1051a39Sopenharmony_ci    }
78e1051a39Sopenharmony_ci
79e1051a39Sopenharmony_ci    entl = (uint16_t)(8 * id_len);
80e1051a39Sopenharmony_ci
81e1051a39Sopenharmony_ci    e_byte = entl >> 8;
82e1051a39Sopenharmony_ci    if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
83e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
84e1051a39Sopenharmony_ci        goto done;
85e1051a39Sopenharmony_ci    }
86e1051a39Sopenharmony_ci    e_byte = entl & 0xFF;
87e1051a39Sopenharmony_ci    if (!EVP_DigestUpdate(hash, &e_byte, 1)) {
88e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
89e1051a39Sopenharmony_ci        goto done;
90e1051a39Sopenharmony_ci    }
91e1051a39Sopenharmony_ci
92e1051a39Sopenharmony_ci    if (id_len > 0 && !EVP_DigestUpdate(hash, id, id_len)) {
93e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
94e1051a39Sopenharmony_ci        goto done;
95e1051a39Sopenharmony_ci    }
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ci    if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
98e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
99e1051a39Sopenharmony_ci        goto done;
100e1051a39Sopenharmony_ci    }
101e1051a39Sopenharmony_ci
102e1051a39Sopenharmony_ci    p_bytes = BN_num_bytes(p);
103e1051a39Sopenharmony_ci    buf = OPENSSL_zalloc(p_bytes);
104e1051a39Sopenharmony_ci    if (buf == NULL) {
105e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
106e1051a39Sopenharmony_ci        goto done;
107e1051a39Sopenharmony_ci    }
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ci    if (BN_bn2binpad(a, buf, p_bytes) < 0
110e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, buf, p_bytes)
111e1051a39Sopenharmony_ci            || BN_bn2binpad(b, buf, p_bytes) < 0
112e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, buf, p_bytes)
113e1051a39Sopenharmony_ci            || !EC_POINT_get_affine_coordinates(group,
114e1051a39Sopenharmony_ci                                                EC_GROUP_get0_generator(group),
115e1051a39Sopenharmony_ci                                                xG, yG, ctx)
116e1051a39Sopenharmony_ci            || BN_bn2binpad(xG, buf, p_bytes) < 0
117e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, buf, p_bytes)
118e1051a39Sopenharmony_ci            || BN_bn2binpad(yG, buf, p_bytes) < 0
119e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, buf, p_bytes)
120e1051a39Sopenharmony_ci            || !EC_POINT_get_affine_coordinates(group,
121e1051a39Sopenharmony_ci                                                EC_KEY_get0_public_key(key),
122e1051a39Sopenharmony_ci                                                xA, yA, ctx)
123e1051a39Sopenharmony_ci            || BN_bn2binpad(xA, buf, p_bytes) < 0
124e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, buf, p_bytes)
125e1051a39Sopenharmony_ci            || BN_bn2binpad(yA, buf, p_bytes) < 0
126e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, buf, p_bytes)
127e1051a39Sopenharmony_ci            || !EVP_DigestFinal(hash, out, NULL)) {
128e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
129e1051a39Sopenharmony_ci        goto done;
130e1051a39Sopenharmony_ci    }
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_ci    rc = 1;
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci done:
135e1051a39Sopenharmony_ci    OPENSSL_free(buf);
136e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
137e1051a39Sopenharmony_ci    EVP_MD_CTX_free(hash);
138e1051a39Sopenharmony_ci    return rc;
139e1051a39Sopenharmony_ci}
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_cistatic BIGNUM *sm2_compute_msg_hash(const EVP_MD *digest,
142e1051a39Sopenharmony_ci                                    const EC_KEY *key,
143e1051a39Sopenharmony_ci                                    const uint8_t *id,
144e1051a39Sopenharmony_ci                                    const size_t id_len,
145e1051a39Sopenharmony_ci                                    const uint8_t *msg, size_t msg_len)
146e1051a39Sopenharmony_ci{
147e1051a39Sopenharmony_ci    EVP_MD_CTX *hash = EVP_MD_CTX_new();
148e1051a39Sopenharmony_ci    const int md_size = EVP_MD_get_size(digest);
149e1051a39Sopenharmony_ci    uint8_t *z = NULL;
150e1051a39Sopenharmony_ci    BIGNUM *e = NULL;
151e1051a39Sopenharmony_ci    EVP_MD *fetched_digest = NULL;
152e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
153e1051a39Sopenharmony_ci    const char *propq = ossl_ec_key_get0_propq(key);
154e1051a39Sopenharmony_ci
155e1051a39Sopenharmony_ci    if (md_size < 0) {
156e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_DIGEST);
157e1051a39Sopenharmony_ci        goto done;
158e1051a39Sopenharmony_ci    }
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci    z = OPENSSL_zalloc(md_size);
161e1051a39Sopenharmony_ci    if (hash == NULL || z == NULL) {
162e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
163e1051a39Sopenharmony_ci        goto done;
164e1051a39Sopenharmony_ci    }
165e1051a39Sopenharmony_ci
166e1051a39Sopenharmony_ci    fetched_digest = EVP_MD_fetch(libctx, EVP_MD_get0_name(digest), propq);
167e1051a39Sopenharmony_ci    if (fetched_digest == NULL) {
168e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
169e1051a39Sopenharmony_ci        goto done;
170e1051a39Sopenharmony_ci    }
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ci    if (!ossl_sm2_compute_z_digest(z, fetched_digest, id, id_len, key)) {
173e1051a39Sopenharmony_ci        /* SM2err already called */
174e1051a39Sopenharmony_ci        goto done;
175e1051a39Sopenharmony_ci    }
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci    if (!EVP_DigestInit(hash, fetched_digest)
178e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, z, md_size)
179e1051a39Sopenharmony_ci            || !EVP_DigestUpdate(hash, msg, msg_len)
180e1051a39Sopenharmony_ci               /* reuse z buffer to hold H(Z || M) */
181e1051a39Sopenharmony_ci            || !EVP_DigestFinal(hash, z, NULL)) {
182e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_EVP_LIB);
183e1051a39Sopenharmony_ci        goto done;
184e1051a39Sopenharmony_ci    }
185e1051a39Sopenharmony_ci
186e1051a39Sopenharmony_ci    e = BN_bin2bn(z, md_size, NULL);
187e1051a39Sopenharmony_ci    if (e == NULL)
188e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ci done:
191e1051a39Sopenharmony_ci    EVP_MD_free(fetched_digest);
192e1051a39Sopenharmony_ci    OPENSSL_free(z);
193e1051a39Sopenharmony_ci    EVP_MD_CTX_free(hash);
194e1051a39Sopenharmony_ci    return e;
195e1051a39Sopenharmony_ci}
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_cistatic ECDSA_SIG *sm2_sig_gen(const EC_KEY *key, const BIGNUM *e)
198e1051a39Sopenharmony_ci{
199e1051a39Sopenharmony_ci    const BIGNUM *dA = EC_KEY_get0_private_key(key);
200e1051a39Sopenharmony_ci    const EC_GROUP *group = EC_KEY_get0_group(key);
201e1051a39Sopenharmony_ci    const BIGNUM *order = EC_GROUP_get0_order(group);
202e1051a39Sopenharmony_ci    ECDSA_SIG *sig = NULL;
203e1051a39Sopenharmony_ci    EC_POINT *kG = NULL;
204e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
205e1051a39Sopenharmony_ci    BIGNUM *k = NULL;
206e1051a39Sopenharmony_ci    BIGNUM *rk = NULL;
207e1051a39Sopenharmony_ci    BIGNUM *r = NULL;
208e1051a39Sopenharmony_ci    BIGNUM *s = NULL;
209e1051a39Sopenharmony_ci    BIGNUM *x1 = NULL;
210e1051a39Sopenharmony_ci    BIGNUM *tmp = NULL;
211e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
212e1051a39Sopenharmony_ci
213e1051a39Sopenharmony_ci    kG = EC_POINT_new(group);
214e1051a39Sopenharmony_ci    ctx = BN_CTX_new_ex(libctx);
215e1051a39Sopenharmony_ci    if (kG == NULL || ctx == NULL) {
216e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
217e1051a39Sopenharmony_ci        goto done;
218e1051a39Sopenharmony_ci    }
219e1051a39Sopenharmony_ci
220e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
221e1051a39Sopenharmony_ci    k = BN_CTX_get(ctx);
222e1051a39Sopenharmony_ci    rk = BN_CTX_get(ctx);
223e1051a39Sopenharmony_ci    x1 = BN_CTX_get(ctx);
224e1051a39Sopenharmony_ci    tmp = BN_CTX_get(ctx);
225e1051a39Sopenharmony_ci    if (tmp == NULL) {
226e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
227e1051a39Sopenharmony_ci        goto done;
228e1051a39Sopenharmony_ci    }
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci    /*
231e1051a39Sopenharmony_ci     * These values are returned and so should not be allocated out of the
232e1051a39Sopenharmony_ci     * context
233e1051a39Sopenharmony_ci     */
234e1051a39Sopenharmony_ci    r = BN_new();
235e1051a39Sopenharmony_ci    s = BN_new();
236e1051a39Sopenharmony_ci
237e1051a39Sopenharmony_ci    if (r == NULL || s == NULL) {
238e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
239e1051a39Sopenharmony_ci        goto done;
240e1051a39Sopenharmony_ci    }
241e1051a39Sopenharmony_ci
242e1051a39Sopenharmony_ci    /*
243e1051a39Sopenharmony_ci     * A3: Generate a random number k in [1,n-1] using random number generators;
244e1051a39Sopenharmony_ci     * A4: Compute (x1,y1)=[k]G, and convert the type of data x1 to be integer
245e1051a39Sopenharmony_ci     *     as specified in clause 4.2.8 of GM/T 0003.1-2012;
246e1051a39Sopenharmony_ci     * A5: Compute r=(e+x1) mod n. If r=0 or r+k=n, then go to A3;
247e1051a39Sopenharmony_ci     * A6: Compute s=(1/(1+dA)*(k-r*dA)) mod n. If s=0, then go to A3;
248e1051a39Sopenharmony_ci     * A7: Convert the type of data (r,s) to be bit strings according to the details
249e1051a39Sopenharmony_ci     *     in clause 4.2.2 of GM/T 0003.1-2012. Then the signature of message M is (r,s).
250e1051a39Sopenharmony_ci     */
251e1051a39Sopenharmony_ci    for (;;) {
252e1051a39Sopenharmony_ci        if (!BN_priv_rand_range_ex(k, order, 0, ctx)) {
253e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
254e1051a39Sopenharmony_ci            goto done;
255e1051a39Sopenharmony_ci        }
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_ci        if (!EC_POINT_mul(group, kG, k, NULL, NULL, ctx)
258e1051a39Sopenharmony_ci                || !EC_POINT_get_affine_coordinates(group, kG, x1, NULL,
259e1051a39Sopenharmony_ci                                                    ctx)
260e1051a39Sopenharmony_ci                || !BN_mod_add(r, e, x1, order, ctx)) {
261e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
262e1051a39Sopenharmony_ci            goto done;
263e1051a39Sopenharmony_ci        }
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci        /* try again if r == 0 or r+k == n */
266e1051a39Sopenharmony_ci        if (BN_is_zero(r))
267e1051a39Sopenharmony_ci            continue;
268e1051a39Sopenharmony_ci
269e1051a39Sopenharmony_ci        if (!BN_add(rk, r, k)) {
270e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
271e1051a39Sopenharmony_ci            goto done;
272e1051a39Sopenharmony_ci        }
273e1051a39Sopenharmony_ci
274e1051a39Sopenharmony_ci        if (BN_cmp(rk, order) == 0)
275e1051a39Sopenharmony_ci            continue;
276e1051a39Sopenharmony_ci
277e1051a39Sopenharmony_ci        if (!BN_add(s, dA, BN_value_one())
278e1051a39Sopenharmony_ci                || !ossl_ec_group_do_inverse_ord(group, s, s, ctx)
279e1051a39Sopenharmony_ci                || !BN_mod_mul(tmp, dA, r, order, ctx)
280e1051a39Sopenharmony_ci                || !BN_sub(tmp, k, tmp)
281e1051a39Sopenharmony_ci                || !BN_mod_mul(s, s, tmp, order, ctx)) {
282e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
283e1051a39Sopenharmony_ci            goto done;
284e1051a39Sopenharmony_ci        }
285e1051a39Sopenharmony_ci
286e1051a39Sopenharmony_ci        /* try again if s == 0 */
287e1051a39Sopenharmony_ci        if (BN_is_zero(s))
288e1051a39Sopenharmony_ci            continue;
289e1051a39Sopenharmony_ci
290e1051a39Sopenharmony_ci        sig = ECDSA_SIG_new();
291e1051a39Sopenharmony_ci        if (sig == NULL) {
292e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
293e1051a39Sopenharmony_ci            goto done;
294e1051a39Sopenharmony_ci        }
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_ci         /* takes ownership of r and s */
297e1051a39Sopenharmony_ci        ECDSA_SIG_set0(sig, r, s);
298e1051a39Sopenharmony_ci        break;
299e1051a39Sopenharmony_ci    }
300e1051a39Sopenharmony_ci
301e1051a39Sopenharmony_ci done:
302e1051a39Sopenharmony_ci    if (sig == NULL) {
303e1051a39Sopenharmony_ci        BN_free(r);
304e1051a39Sopenharmony_ci        BN_free(s);
305e1051a39Sopenharmony_ci    }
306e1051a39Sopenharmony_ci
307e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
308e1051a39Sopenharmony_ci    EC_POINT_free(kG);
309e1051a39Sopenharmony_ci    return sig;
310e1051a39Sopenharmony_ci}
311e1051a39Sopenharmony_ci
312e1051a39Sopenharmony_cistatic int sm2_sig_verify(const EC_KEY *key, const ECDSA_SIG *sig,
313e1051a39Sopenharmony_ci                          const BIGNUM *e)
314e1051a39Sopenharmony_ci{
315e1051a39Sopenharmony_ci    int ret = 0;
316e1051a39Sopenharmony_ci    const EC_GROUP *group = EC_KEY_get0_group(key);
317e1051a39Sopenharmony_ci    const BIGNUM *order = EC_GROUP_get0_order(group);
318e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
319e1051a39Sopenharmony_ci    EC_POINT *pt = NULL;
320e1051a39Sopenharmony_ci    BIGNUM *t = NULL;
321e1051a39Sopenharmony_ci    BIGNUM *x1 = NULL;
322e1051a39Sopenharmony_ci    const BIGNUM *r = NULL;
323e1051a39Sopenharmony_ci    const BIGNUM *s = NULL;
324e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = ossl_ec_key_get_libctx(key);
325e1051a39Sopenharmony_ci
326e1051a39Sopenharmony_ci    ctx = BN_CTX_new_ex(libctx);
327e1051a39Sopenharmony_ci    pt = EC_POINT_new(group);
328e1051a39Sopenharmony_ci    if (ctx == NULL || pt == NULL) {
329e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
330e1051a39Sopenharmony_ci        goto done;
331e1051a39Sopenharmony_ci    }
332e1051a39Sopenharmony_ci
333e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
334e1051a39Sopenharmony_ci    t = BN_CTX_get(ctx);
335e1051a39Sopenharmony_ci    x1 = BN_CTX_get(ctx);
336e1051a39Sopenharmony_ci    if (x1 == NULL) {
337e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
338e1051a39Sopenharmony_ci        goto done;
339e1051a39Sopenharmony_ci    }
340e1051a39Sopenharmony_ci
341e1051a39Sopenharmony_ci    /*
342e1051a39Sopenharmony_ci     * B1: verify whether r' in [1,n-1], verification failed if not
343e1051a39Sopenharmony_ci     * B2: verify whether s' in [1,n-1], verification failed if not
344e1051a39Sopenharmony_ci     * B3: set M'~=ZA || M'
345e1051a39Sopenharmony_ci     * B4: calculate e'=Hv(M'~)
346e1051a39Sopenharmony_ci     * B5: calculate t = (r' + s') modn, verification failed if t=0
347e1051a39Sopenharmony_ci     * B6: calculate the point (x1', y1')=[s']G + [t]PA
348e1051a39Sopenharmony_ci     * B7: calculate R=(e'+x1') modn, verification pass if yes, otherwise failed
349e1051a39Sopenharmony_ci     */
350e1051a39Sopenharmony_ci
351e1051a39Sopenharmony_ci    ECDSA_SIG_get0(sig, &r, &s);
352e1051a39Sopenharmony_ci
353e1051a39Sopenharmony_ci    if (BN_cmp(r, BN_value_one()) < 0
354e1051a39Sopenharmony_ci            || BN_cmp(s, BN_value_one()) < 0
355e1051a39Sopenharmony_ci            || BN_cmp(order, r) <= 0
356e1051a39Sopenharmony_ci            || BN_cmp(order, s) <= 0) {
357e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE);
358e1051a39Sopenharmony_ci        goto done;
359e1051a39Sopenharmony_ci    }
360e1051a39Sopenharmony_ci
361e1051a39Sopenharmony_ci    if (!BN_mod_add(t, r, s, order, ctx)) {
362e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
363e1051a39Sopenharmony_ci        goto done;
364e1051a39Sopenharmony_ci    }
365e1051a39Sopenharmony_ci
366e1051a39Sopenharmony_ci    if (BN_is_zero(t)) {
367e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, SM2_R_BAD_SIGNATURE);
368e1051a39Sopenharmony_ci        goto done;
369e1051a39Sopenharmony_ci    }
370e1051a39Sopenharmony_ci
371e1051a39Sopenharmony_ci    if (!EC_POINT_mul(group, pt, s, EC_KEY_get0_public_key(key), t, ctx)
372e1051a39Sopenharmony_ci            || !EC_POINT_get_affine_coordinates(group, pt, x1, NULL, ctx)) {
373e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_EC_LIB);
374e1051a39Sopenharmony_ci        goto done;
375e1051a39Sopenharmony_ci    }
376e1051a39Sopenharmony_ci
377e1051a39Sopenharmony_ci    if (!BN_mod_add(t, e, x1, order, ctx)) {
378e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
379e1051a39Sopenharmony_ci        goto done;
380e1051a39Sopenharmony_ci    }
381e1051a39Sopenharmony_ci
382e1051a39Sopenharmony_ci    if (BN_cmp(r, t) == 0)
383e1051a39Sopenharmony_ci        ret = 1;
384e1051a39Sopenharmony_ci
385e1051a39Sopenharmony_ci done:
386e1051a39Sopenharmony_ci    EC_POINT_free(pt);
387e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
388e1051a39Sopenharmony_ci    return ret;
389e1051a39Sopenharmony_ci}
390e1051a39Sopenharmony_ci
391e1051a39Sopenharmony_ciECDSA_SIG *ossl_sm2_do_sign(const EC_KEY *key,
392e1051a39Sopenharmony_ci                            const EVP_MD *digest,
393e1051a39Sopenharmony_ci                            const uint8_t *id,
394e1051a39Sopenharmony_ci                            const size_t id_len,
395e1051a39Sopenharmony_ci                            const uint8_t *msg, size_t msg_len)
396e1051a39Sopenharmony_ci{
397e1051a39Sopenharmony_ci    BIGNUM *e = NULL;
398e1051a39Sopenharmony_ci    ECDSA_SIG *sig = NULL;
399e1051a39Sopenharmony_ci
400e1051a39Sopenharmony_ci    e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
401e1051a39Sopenharmony_ci    if (e == NULL) {
402e1051a39Sopenharmony_ci        /* SM2err already called */
403e1051a39Sopenharmony_ci        goto done;
404e1051a39Sopenharmony_ci    }
405e1051a39Sopenharmony_ci
406e1051a39Sopenharmony_ci    sig = sm2_sig_gen(key, e);
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci done:
409e1051a39Sopenharmony_ci    BN_free(e);
410e1051a39Sopenharmony_ci    return sig;
411e1051a39Sopenharmony_ci}
412e1051a39Sopenharmony_ci
413e1051a39Sopenharmony_ciint ossl_sm2_do_verify(const EC_KEY *key,
414e1051a39Sopenharmony_ci                       const EVP_MD *digest,
415e1051a39Sopenharmony_ci                       const ECDSA_SIG *sig,
416e1051a39Sopenharmony_ci                       const uint8_t *id,
417e1051a39Sopenharmony_ci                       const size_t id_len,
418e1051a39Sopenharmony_ci                       const uint8_t *msg, size_t msg_len)
419e1051a39Sopenharmony_ci{
420e1051a39Sopenharmony_ci    BIGNUM *e = NULL;
421e1051a39Sopenharmony_ci    int ret = 0;
422e1051a39Sopenharmony_ci
423e1051a39Sopenharmony_ci    e = sm2_compute_msg_hash(digest, key, id, id_len, msg, msg_len);
424e1051a39Sopenharmony_ci    if (e == NULL) {
425e1051a39Sopenharmony_ci        /* SM2err already called */
426e1051a39Sopenharmony_ci        goto done;
427e1051a39Sopenharmony_ci    }
428e1051a39Sopenharmony_ci
429e1051a39Sopenharmony_ci    ret = sm2_sig_verify(key, sig, e);
430e1051a39Sopenharmony_ci
431e1051a39Sopenharmony_ci done:
432e1051a39Sopenharmony_ci    BN_free(e);
433e1051a39Sopenharmony_ci    return ret;
434e1051a39Sopenharmony_ci}
435e1051a39Sopenharmony_ci
436e1051a39Sopenharmony_ciint ossl_sm2_internal_sign(const unsigned char *dgst, int dgstlen,
437e1051a39Sopenharmony_ci                           unsigned char *sig, unsigned int *siglen,
438e1051a39Sopenharmony_ci                           EC_KEY *eckey)
439e1051a39Sopenharmony_ci{
440e1051a39Sopenharmony_ci    BIGNUM *e = NULL;
441e1051a39Sopenharmony_ci    ECDSA_SIG *s = NULL;
442e1051a39Sopenharmony_ci    int sigleni;
443e1051a39Sopenharmony_ci    int ret = -1;
444e1051a39Sopenharmony_ci
445e1051a39Sopenharmony_ci    if (sig == NULL) {
446e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_PASSED_NULL_PARAMETER);
447e1051a39Sopenharmony_ci        goto done;
448e1051a39Sopenharmony_ci    }
449e1051a39Sopenharmony_ci
450e1051a39Sopenharmony_ci    e = BN_bin2bn(dgst, dgstlen, NULL);
451e1051a39Sopenharmony_ci    if (e == NULL) {
452e1051a39Sopenharmony_ci       ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
453e1051a39Sopenharmony_ci       goto done;
454e1051a39Sopenharmony_ci    }
455e1051a39Sopenharmony_ci
456e1051a39Sopenharmony_ci    s = sm2_sig_gen(eckey, e);
457e1051a39Sopenharmony_ci    if (s == NULL) {
458e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
459e1051a39Sopenharmony_ci        goto done;
460e1051a39Sopenharmony_ci    }
461e1051a39Sopenharmony_ci
462e1051a39Sopenharmony_ci    sigleni = i2d_ECDSA_SIG(s, &sig);
463e1051a39Sopenharmony_ci    if (sigleni < 0) {
464e1051a39Sopenharmony_ci       ERR_raise(ERR_LIB_SM2, ERR_R_INTERNAL_ERROR);
465e1051a39Sopenharmony_ci       goto done;
466e1051a39Sopenharmony_ci    }
467e1051a39Sopenharmony_ci    *siglen = (unsigned int)sigleni;
468e1051a39Sopenharmony_ci
469e1051a39Sopenharmony_ci    ret = 1;
470e1051a39Sopenharmony_ci
471e1051a39Sopenharmony_ci done:
472e1051a39Sopenharmony_ci    ECDSA_SIG_free(s);
473e1051a39Sopenharmony_ci    BN_free(e);
474e1051a39Sopenharmony_ci    return ret;
475e1051a39Sopenharmony_ci}
476e1051a39Sopenharmony_ci
477e1051a39Sopenharmony_ciint ossl_sm2_internal_verify(const unsigned char *dgst, int dgstlen,
478e1051a39Sopenharmony_ci                             const unsigned char *sig, int sig_len,
479e1051a39Sopenharmony_ci                             EC_KEY *eckey)
480e1051a39Sopenharmony_ci{
481e1051a39Sopenharmony_ci    ECDSA_SIG *s = NULL;
482e1051a39Sopenharmony_ci    BIGNUM *e = NULL;
483e1051a39Sopenharmony_ci    const unsigned char *p = sig;
484e1051a39Sopenharmony_ci    unsigned char *der = NULL;
485e1051a39Sopenharmony_ci    int derlen = -1;
486e1051a39Sopenharmony_ci    int ret = -1;
487e1051a39Sopenharmony_ci
488e1051a39Sopenharmony_ci    s = ECDSA_SIG_new();
489e1051a39Sopenharmony_ci    if (s == NULL) {
490e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_MALLOC_FAILURE);
491e1051a39Sopenharmony_ci        goto done;
492e1051a39Sopenharmony_ci    }
493e1051a39Sopenharmony_ci    if (d2i_ECDSA_SIG(&s, &p, sig_len) == NULL) {
494e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
495e1051a39Sopenharmony_ci        goto done;
496e1051a39Sopenharmony_ci    }
497e1051a39Sopenharmony_ci    /* Ensure signature uses DER and doesn't have trailing garbage */
498e1051a39Sopenharmony_ci    derlen = i2d_ECDSA_SIG(s, &der);
499e1051a39Sopenharmony_ci    if (derlen != sig_len || memcmp(sig, der, derlen) != 0) {
500e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, SM2_R_INVALID_ENCODING);
501e1051a39Sopenharmony_ci        goto done;
502e1051a39Sopenharmony_ci    }
503e1051a39Sopenharmony_ci
504e1051a39Sopenharmony_ci    e = BN_bin2bn(dgst, dgstlen, NULL);
505e1051a39Sopenharmony_ci    if (e == NULL) {
506e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_SM2, ERR_R_BN_LIB);
507e1051a39Sopenharmony_ci        goto done;
508e1051a39Sopenharmony_ci    }
509e1051a39Sopenharmony_ci
510e1051a39Sopenharmony_ci    ret = sm2_sig_verify(eckey, s, e);
511e1051a39Sopenharmony_ci
512e1051a39Sopenharmony_ci done:
513e1051a39Sopenharmony_ci    OPENSSL_free(der);
514e1051a39Sopenharmony_ci    BN_free(e);
515e1051a39Sopenharmony_ci    ECDSA_SIG_free(s);
516e1051a39Sopenharmony_ci    return ret;
517e1051a39Sopenharmony_ci}
518