• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #if defined(HITLS_CRYPTO_CURVE_SM2) && defined(HITLS_SIXTY_FOUR_BITS)
18 
19 #include <stdint.h>
20 #include "securec.h"
21 #include "crypt_ecc.h"
22 #include "ecc_local.h"
23 #include "crypt_utils.h"
24 #include "crypt_errno.h"
25 #include "bsl_sal.h"
26 #include "bsl_err_internal.h"
27 #include "asm_ecp_sm2.h"
28 
29 #define SM2_MASK2 0xff
30 #define WINDOW_SIZE 4
31 #define PRECOMPUTED_TABLE_SIZE (1 << WINDOW_SIZE)
32 #define WINDOW_HALF_TABLE_SIZE 8
33 #define SM2_NUMTOOFFSET(num) (((num) < 0) ? (WINDOW_HALF_TABLE_SIZE - 1 - (((num) - 1) >> 1)) : (((num) - 1) >> 1))
34 
35 static const BN_UINT g_sm2p[SM2_LIMBS] = {
36     0xffffffffffffffff, 0xffffffff00000000,
37     0xffffffffffffffff, 0xfffffffeffffffff
38 };
39 
40 static const BN_UINT g_sm2ord[SM2_LIMBS] = {
41     0x53bbf40939d54123, 0x7203df6b21c6052b,
42     0xffffffffffffffff, 0xfffffffeffffffff
43 };
44 
45 static const BN_UINT g_one[SM2_LIMBS] = {1, 0, 0, 0};
46 
47 #define FDIV(uout, uin, xout, xin, div, mod)         \
48     do {                                             \
49         ECP_Sm2Div##div(uout, uin);                      \
50         ECP_Sm2Div##div##Mod##mod(xout, xin); \
51     } while (0)
52 
53 #define FSUB(uout, uin, xout, xin, mod)             \
54     do {                                            \
55         ECP_Sm2BnSub(uout, uout, uin);                    \
56         ECP_Sm2SubMod##mod(xout, xout, xin); \
57     } while (0)
58 
59 #define FSUB_DIV(u, v, x1, x2, div, mod)  \
60     do {                                  \
61         if (IsGreater(u, v) == 1) {      \
62             FSUB(u, v, x1, x2, mod);      \
63             FDIV(u, u, x1, x1, div, mod); \
64         } else {                          \
65             FSUB(v, u, x2, x1, mod);      \
66             FDIV(v, v, x2, x2, div, mod); \
67         }                                 \
68     } while (0)
69 
IsZero(BN_UINT a)70 static uint32_t IsZero(BN_UINT a)
71 {
72     BN_UINT t = a;
73     t |= (0 - t);
74     t = ~t;
75     t >>= (BN_UNIT_BITS - 1);
76     return (uint32_t)t;
77 }
78 
IsZeros(const BN_UINT * a)79 static uint32_t IsZeros(const BN_UINT *a)
80 {
81     BN_UINT res = a[0] ^ 0;
82     for (uint32_t i = 1; i < SM2_LIMBS; i++) {
83         res |= a[i] ^ 0;
84     }
85     return IsZero(res);
86 }
87 
IsEqual(const BN_UINT * a,const BN_UINT * b)88 static uint32_t IsEqual(const BN_UINT *a, const BN_UINT *b)
89 {
90     BN_UINT res = a[0] ^ b[0];
91     for (uint32_t i = 1; i < SM2_LIMBS; i++) {
92         res |= a[i] ^ b[i];
93     }
94     return IsZero(res);
95 }
96 
97 #define IS_ONE(a) IsEqual(a, g_one)
98 
IsGreater(const BN_UINT * a,const BN_UINT * b)99 static int32_t IsGreater(const BN_UINT *a, const BN_UINT *b)
100 {
101     for (int32_t i = (int32_t)(SM2_LIMBS - 1); i >= 0; --i) {
102         if (a[i] > b[i]) {
103             return 1;
104         }
105         if (a[i] < b[i]) {
106             return -1;
107         }
108     }
109 
110     return 0;
111 }
112 
113 /*
114  * Radix-4 Binary algorithm for modular inversion in Fp
115  * ref. <Ultra High-Speed SM2 ASIC Implementation>
116 */
117 
118 /* Modular inv: out = in^(-1) mod p */
ECP_Sm2ModInverse(BN_UINT * out,const BN_UINT * in)119 static void ECP_Sm2ModInverse(BN_UINT *out, const BN_UINT *in)
120 {
121     BN_UINT u[SM2_LIMBS] ALIGN32;
122     BN_UINT v[SM2_LIMBS] ALIGN32;
123     BN_UINT x1[SM2_LIMBS] ALIGN32 = {1, 0, 0, 0};
124     BN_UINT x2[SM2_LIMBS] ALIGN32 = {0};
125     BN_UINT c;
126     BN_UINT d;
127     if (IsZeros(in) != 0) {
128         return;
129     }
130     (void)memcpy_s(u, SM2_BYTES_NUM, in, SM2_BYTES_NUM);
131     (void)memcpy_s(v, SM2_BYTES_NUM, g_sm2p, SM2_BYTES_NUM);
132     while (((!IS_ONE(u)) != 0) && ((!IS_ONE(v)) != 0)) {
133         c = u[0] & 0x3; // Use 0x03 to obtain the last two bits.
134         d = v[0] & 0x3;
135         if (c == 0) {
136             FDIV(u, u, x1, x1, 4, P);
137         } else if (d == 0) {
138             FDIV(v, v, x2, x2, 4, P);
139         } else if (c == d) {
140             FSUB_DIV(u, v, x1, x2, 4, P);
141         } else if (c == 2) { // if c == 2
142             FDIV(u, u, x1, x1, 2, P);
143             FSUB_DIV(u, v, x1, x2, 2, P);
144         } else if (d == 2) { // if d == 2
145             FDIV(v, v, x2, x2, 2, P);
146             FSUB_DIV(u, v, x1, x2, 2, P);
147         } else {
148             FSUB_DIV(u, v, x1, x2, 2, P);
149         }
150     }
151     if (IS_ONE(u) != 0) {
152         (void)memcpy_s(out, SM2_BYTES_NUM, x1, SM2_BYTES_NUM);
153     } else {
154         (void)memcpy_s(out, SM2_BYTES_NUM, x2, SM2_BYTES_NUM);
155     }
156 }
157 
158 /* Modular inv: out = in^(-1) mod n, where n = ord(p) */
ECP_Sm2InvModOrd(BN_UINT * out,const BN_UINT * in)159 static void ECP_Sm2InvModOrd(BN_UINT *out, const BN_UINT *in)
160 {
161     BN_UINT u[SM2_LIMBS] ALIGN32;
162     BN_UINT v[SM2_LIMBS] ALIGN32;
163     BN_UINT x1[SM2_LIMBS] ALIGN32 = {1, 0, 0, 0};
164     BN_UINT x2[SM2_LIMBS] ALIGN32 = {0};
165     BN_UINT c;
166     BN_UINT d;
167     if (IsZeros(in) != 0) {
168         return;
169     }
170     (void)memcpy_s(u, SM2_BYTES_NUM, in, SM2_BYTES_NUM);
171     (void)memcpy_s(v, SM2_BYTES_NUM, g_sm2ord, SM2_BYTES_NUM);
172     while (((!IS_ONE(u)) != 0) && ((!IS_ONE(v)) != 0)) {
173         c = u[0] & 0x3; // Use 0x03 to obtain the last two bits.
174         d = v[0] & 0x3;
175         if (c == 0) {
176             FDIV(u, u, x1, x1, 4, Ord);
177         } else if (d == 0) {
178             FDIV(v, v, x2, x2, 4, Ord);
179         } else if (c == d) {
180             FSUB_DIV(u, v, x1, x2, 4, Ord);
181         } else if (c == 2) { // if c == 2
182             FDIV(u, u, x1, x1, 2, Ord);
183             FSUB_DIV(u, v, x1, x2, 2, Ord);
184         } else if (d == 2) { // if d == 2
185             FDIV(v, v, x2, x2, 2, Ord);
186             FSUB_DIV(u, v, x1, x2, 2, Ord);
187         } else {
188             FSUB_DIV(u, v, x1, x2, 2, Ord);
189         }
190     }
191     if (IS_ONE(u) != 0) {
192         (void)memcpy_s(out, SM2_BYTES_NUM, x1, SM2_BYTES_NUM);
193     } else {
194         (void)memcpy_s(out, SM2_BYTES_NUM, x2, SM2_BYTES_NUM);
195     }
196 }
197 
ECP_Sm2Point2Array(SM2_point * r,const ECC_Point * p)198 static int32_t ECP_Sm2Point2Array(SM2_point *r, const ECC_Point *p)
199 {
200     int32_t ret;
201     uint32_t len = SM2_LIMBS;
202     GOTO_ERR_IF_EX(BN_Bn2U64Array(p->x, (BN_UINT *)&r->x, &len), ret);
203     GOTO_ERR_IF_EX(BN_Bn2U64Array(p->y, (BN_UINT *)&r->y, &len), ret);
204     GOTO_ERR_IF_EX(BN_Bn2U64Array(p->z, (BN_UINT *)&r->z, &len), ret);
205 ERR:
206     return ret;
207 }
208 
ECP_Sm2Array2Point(ECC_Point * r,const SM2_point * a)209 static int32_t ECP_Sm2Array2Point(ECC_Point *r, const SM2_point *a)
210 {
211     int32_t ret;
212     GOTO_ERR_IF_EX(BN_U64Array2Bn(r->x, (const BN_UINT *)a->x, SM2_LIMBS), ret);
213     GOTO_ERR_IF_EX(BN_U64Array2Bn(r->y, (const BN_UINT *)a->y, SM2_LIMBS), ret);
214     GOTO_ERR_IF_EX(BN_U64Array2Bn(r->z, (const BN_UINT *)a->z, SM2_LIMBS), ret);
215 ERR:
216     return ret;
217 }
218 
ECP_Sm2GetAffine(SM2_AffinePoint * r,const SM2_point * a)219 int32_t ECP_Sm2GetAffine(SM2_AffinePoint *r, const SM2_point *a)
220 {
221     BN_UINT zInv3[SM2_LIMBS] ALIGN32 = {0};
222     BN_UINT zInv2[SM2_LIMBS] ALIGN32 = {0};
223     if (IsZeros(a->z) != 0) {
224         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
225         return CRYPT_ECC_POINT_AT_INFINITY;
226     }
227     if (IsEqual(a->z, g_one) != 0) {
228         (void)memcpy_s(r->x, sizeof(r->x), a->x, sizeof(r->x));
229         (void)memcpy_s(r->y, sizeof(r->y), a->y, sizeof(r->x));
230         return CRYPT_SUCCESS;
231     }
232 
233     ECP_Sm2ModInverse(zInv3, a->z);
234     ECP_Sm2Sqr(zInv2, zInv3);
235     ECP_Sm2Mul(r->x, a->x, zInv2);
236     ECP_Sm2Mul(zInv3, zInv3, zInv2);
237     ECP_Sm2Mul(r->y, a->y, zInv3);
238 
239     return CRYPT_SUCCESS;
240 }
241 
ECP_Sm2Point2Affine(const ECC_Para * para,ECC_Point * r,const ECC_Point * a)242 int32_t ECP_Sm2Point2Affine(const ECC_Para *para, ECC_Point *r, const ECC_Point *a)
243 {
244     if (r == NULL || a == NULL || para == NULL) {
245         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
246         return CRYPT_NULL_INPUT;
247     }
248     if (para->id != CRYPT_ECC_SM2 || r->id != CRYPT_ECC_SM2 || a->id != CRYPT_ECC_SM2) {
249         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
250         return CRYPT_ECC_POINT_ERR_CURVE_ID;
251     }
252 
253     SM2_point temp = {0};
254     SM2_AffinePoint rTemp = {0};
255     int32_t ret;
256     GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&temp, a), ret);
257     GOTO_ERR_IF_EX(ECP_Sm2GetAffine(&rTemp, &temp), ret);
258     GOTO_ERR_IF_EX(BN_Array2BN(r->x, rTemp.x, SM2_LIMBS), ret);
259     GOTO_ERR_IF_EX(BN_Array2BN(r->y, rTemp.y, SM2_LIMBS), ret);
260     GOTO_ERR_IF_EX(BN_SetLimb(r->z, 1), ret);
261 
262 ERR:
263     return ret;
264 }
265 
ECP_Sm2PointDouble(const ECC_Para * para,ECC_Point * r,const ECC_Point * a)266 int32_t ECP_Sm2PointDouble(const ECC_Para *para, ECC_Point *r, const ECC_Point *a)
267 {
268     return ECP_NistPointDouble(para, r, a);
269 }
270 
ECP_Sm2PointAddAffine(const ECC_Para * para,ECC_Point * r,const ECC_Point * a,const ECC_Point * b)271 int32_t ECP_Sm2PointAddAffine(const ECC_Para *para, ECC_Point *r, const ECC_Point *a, const ECC_Point *b)
272 {
273     return ECP_NistPointAddAffine(para, r, a, b);
274 }
275 
ECP_Sm2ScalarMulG(SM2_point * r,const BN_UINT * k)276 static void ECP_Sm2ScalarMulG(SM2_point *r, const BN_UINT *k)
277 {
278     const BN_UINT *precomputed = ECP_Sm2Precomputed();
279     uint32_t index;
280     for (int32_t i = SM2_BYTES_NUM - 1; i >= 0; --i) {
281         index = (k[i / sizeof(BN_UINT)] >> (SM2_BITSOFBYTES * (i % sizeof(BN_UINT)))) & SM2_MASK2;
282 #ifndef HITLS_SM2_PRECOMPUTE_512K_TBL
283         ECP_Sm2PointDoubleMont(r, r);
284         ECP_Sm2PointDoubleMont(r, r);
285         ECP_Sm2PointDoubleMont(r, r);
286         ECP_Sm2PointDoubleMont(r, r);
287         ECP_Sm2PointDoubleMont(r, r);
288         ECP_Sm2PointDoubleMont(r, r);
289         ECP_Sm2PointDoubleMont(r, r);
290         ECP_Sm2PointDoubleMont(r, r);
291 #endif
292         if (index != 0) {
293 #ifdef HITLS_SM2_PRECOMPUTE_512K_TBL
294             index = index + i * SM2_BITS;
295 #endif
296             index = index * SM2_BITSOFBYTES;
297             ECP_Sm2PointAddAffineMont(r, r, (const SM2_AffinePoint *)&precomputed[index]);
298         }
299     }
300 }
301 
ECP_Sm2WnafMul(SM2_point * r,const BN_BigNum * k,SM2_point p)302 static int32_t ECP_Sm2WnafMul(SM2_point *r, const BN_BigNum *k, SM2_point p)
303 {
304     ReCodeData *recodeK = ECC_ReCodeK(k, WINDOW_SIZE);
305     if (recodeK == NULL) {
306         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
307         return CRYPT_MEM_ALLOC_FAIL;
308     }
309     SM2_point doublePoint;
310     SM2_point precomputed[PRECOMPUTED_TABLE_SIZE] ALIGN64;
311     ECP_Sm2ToMont(precomputed[0].x, p.x);
312     ECP_Sm2ToMont(precomputed[0].y, p.y);
313     ECP_Sm2ToMont(precomputed[0].z, p.z);
314     ECP_Sm2PointDoubleMont(&doublePoint, &precomputed[0]);
315 
316     (void)memcpy_s(precomputed[WINDOW_HALF_TABLE_SIZE].x, SM2_BYTES_NUM, precomputed[0].x, SM2_BYTES_NUM);
317     ECP_Sm2Neg(precomputed[WINDOW_HALF_TABLE_SIZE].y, precomputed[0].y);
318     (void)memcpy_s(precomputed[WINDOW_HALF_TABLE_SIZE].z, SM2_BYTES_NUM, precomputed[0].z, SM2_BYTES_NUM);
319 
320     for (uint32_t i = 1; i < WINDOW_HALF_TABLE_SIZE; i++) {
321         ECP_Sm2PointAddMont(&precomputed[i], &precomputed[i - 1], &doublePoint); // 1, 3, 5, 7, 9, 11, 13, 15
322         (void)memcpy_s(precomputed[i + WINDOW_HALF_TABLE_SIZE].x, SM2_BYTES_NUM, precomputed[i].x, SM2_BYTES_NUM);
323         ECP_Sm2Neg(precomputed[i + WINDOW_HALF_TABLE_SIZE].y, precomputed[i].y);
324         (void)memcpy_s(precomputed[i + WINDOW_HALF_TABLE_SIZE].z, SM2_BYTES_NUM, precomputed[i].z, SM2_BYTES_NUM);
325     }
326     int8_t index = SM2_NUMTOOFFSET(recodeK->num[0]);
327     (void)memcpy_s(r, sizeof(SM2_point), &precomputed[index], sizeof(SM2_point));
328     uint32_t w = recodeK->wide[0];
329     while (w != 0) {
330         ECP_Sm2PointDoubleMont(r, r);
331         w--;
332     }
333     for (uint32_t i = 1; i < recodeK->size; i++) {
334         index = SM2_NUMTOOFFSET(recodeK->num[i]);
335         ECP_Sm2PointAddMont(r, r, &precomputed[index]);
336         w = recodeK->wide[i];
337         while (w != 0) {
338             ECP_Sm2PointDoubleMont(r, r);
339             w--;
340         }
341     }
342     ECC_ReCodeFree(recodeK);
343     return CRYPT_SUCCESS;
344 }
345 
ECP_Sm2PointMul(ECC_Para * para,ECC_Point * r,const BN_BigNum * scalar,const ECC_Point * pt)346 int32_t ECP_Sm2PointMul(ECC_Para *para, ECC_Point *r, const BN_BigNum *scalar, const ECC_Point *pt)
347 {
348     if (para == NULL || r == NULL || scalar == NULL) {
349         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
350         return CRYPT_NULL_INPUT;
351     }
352     if (para->id != CRYPT_ECC_SM2 || r->id != CRYPT_ECC_SM2 || (pt != NULL && (pt->id != CRYPT_ECC_SM2))) {
353         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
354         return CRYPT_ECC_POINT_ERR_CURVE_ID;
355     }
356     if (pt != NULL && BN_IsZero(pt->z)) {
357         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
358         return CRYPT_ECC_POINT_AT_INFINITY;
359     }
360     if (BN_IsZero(scalar)) {
361         return BN_Zeroize(r->z);
362     }
363     int32_t ret;
364     BN_UINT k[SM2_LIMBS] = {0};
365     uint32_t klen = SM2_LIMBS;
366     SM2_point re = {0};
367     SM2_point sm2Pt = {0};
368     GOTO_ERR_IF_EX(BN_Bn2U64Array(scalar, k, &klen), ret);
369     if (pt == NULL) {
370         // calculate k*G
371         ECP_Sm2ScalarMulG(&re, k);
372     } else {
373         // point 2 affine
374         GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&sm2Pt, pt), ret);
375         GOTO_ERR_IF_EX(ECP_Sm2WnafMul(&re, scalar, sm2Pt), ret);
376     }
377     ECP_Sm2FromMont(re.x, re.x);
378     ECP_Sm2FromMont(re.y, re.y);
379     ECP_Sm2FromMont(re.z, re.z);
380     // SM2_point 2 ECC_Point
381     GOTO_ERR_IF_EX(ECP_Sm2Array2Point(r, &re), ret);
382 ERR:
383     return ret;
384 }
385 
ECP_Sm2PointMulFast(ECC_Para * para,ECC_Point * r,const BN_BigNum * k,const ECC_Point * pt)386 int32_t ECP_Sm2PointMulFast(ECC_Para *para, ECC_Point *r, const BN_BigNum *k, const ECC_Point *pt)
387 {
388     return ECP_Sm2PointMul(para, r, k, pt);
389 }
390 
ECP_Sm2OrderInv(const ECC_Para * para,BN_BigNum * r,const BN_BigNum * a)391 int32_t ECP_Sm2OrderInv(const ECC_Para *para, BN_BigNum *r, const BN_BigNum *a)
392 {
393     if (para == NULL || r == NULL || a == NULL) {
394         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
395         return CRYPT_NULL_INPUT;
396     }
397     if (BN_IsZero(a)) {
398         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_DIVISOR_ZERO);
399         return CRYPT_BN_ERR_DIVISOR_ZERO;
400     }
401     int32_t ret = BN_Extend(r, SM2_LIMBS);
402     if (ret != CRYPT_SUCCESS) {
403         BSL_ERR_PUSH_ERROR(ret);
404         return ret;
405     }
406     ECP_Sm2InvModOrd(r->data, a->data);
407     r->size = SM2_LIMBS;
408     BN_FixSize(r);
409     if (BN_IsZero(r)) {
410         BSL_ERR_PUSH_ERROR(CRYPT_BN_ERR_NO_INVERSE);
411         return CRYPT_BN_ERR_NO_INVERSE;
412     }
413     return CRYPT_SUCCESS;
414 }
415 
ECP_Sm2PointMulAddCheck(ECC_Para * para,ECC_Point * r,const BN_BigNum * k1,const BN_BigNum * k2,const ECC_Point * pt)416 static int32_t ECP_Sm2PointMulAddCheck(
417     ECC_Para *para, ECC_Point *r, const BN_BigNum *k1, const BN_BigNum *k2, const ECC_Point *pt)
418 {
419     bool flag = (para == NULL || r == NULL || k1 == NULL || k2 == NULL || pt == NULL);
420     uint32_t bits1;
421     uint32_t bits2;
422     if (flag) {
423         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
424         return CRYPT_NULL_INPUT;
425     }
426     if (para->id != CRYPT_ECC_SM2 || r->id != CRYPT_ECC_SM2 || pt->id != CRYPT_ECC_SM2) {
427         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
428         return CRYPT_ECC_POINT_ERR_CURVE_ID;
429     }
430     // Special processing of the infinite point.
431     if (BN_IsZero(pt->z)) {
432         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
433         return CRYPT_ECC_POINT_AT_INFINITY;
434     }
435     bits1 = BN_Bits(k1);
436     bits2 = BN_Bits(k2);
437     if (bits1 > SM2_BITS || bits2 > SM2_BITS) {
438         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_MUL_ERR_K_LEN);
439         return CRYPT_ECC_POINT_MUL_ERR_K_LEN;
440     }
441 
442     return CRYPT_SUCCESS;
443 }
444 
445 // r = k1 * G + k2 * pt
ECP_Sm2PointMulAdd(ECC_Para * para,ECC_Point * r,const BN_BigNum * k1,const BN_BigNum * k2,const ECC_Point * pt)446 int32_t ECP_Sm2PointMulAdd(ECC_Para *para, ECC_Point *r, const BN_BigNum *k1, const BN_BigNum *k2, const ECC_Point *pt)
447 {
448     int32_t ret = ECP_Sm2PointMulAddCheck(para, r, k1, k2, pt);
449     if (ret != CRYPT_SUCCESS) {
450         return ret;
451     }
452     BN_UINT k1Uint[SM2_LIMBS] = {0};
453     uint32_t k1Len = SM2_LIMBS;
454     SM2_point k1G = {0};
455     SM2_point k2Pt = {0};
456     SM2_point sm2Pt = {0};
457     GOTO_ERR_IF_EX(BN_Bn2U64Array(k1, k1Uint, &k1Len), ret);
458     GOTO_ERR_IF_EX(ECP_Sm2Point2Array(&sm2Pt, pt), ret);
459 
460     // k1 * G
461     ECP_Sm2ScalarMulG(&k1G, k1Uint);
462     // k2 * pt
463     GOTO_ERR_IF_EX(ECP_Sm2WnafMul(&k2Pt, k2, sm2Pt), ret);
464     ECP_Sm2PointAddMont(&k2Pt, &k1G, &k2Pt);
465 
466     ECP_Sm2FromMont(k2Pt.x, k2Pt.x);
467     ECP_Sm2FromMont(k2Pt.y, k2Pt.y);
468     ECP_Sm2FromMont(k2Pt.z, k2Pt.z);
469     GOTO_ERR_IF_EX(ECP_Sm2Array2Point(r, &k2Pt), ret);
470 ERR:
471     return ret;
472 }
473 
474 #endif
475