• 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 #ifdef HITLS_CRYPTO_ECC
18 
19 #include "securec.h"
20 #include "bsl_sal.h"
21 #include "bsl_err_internal.h"
22 #include "crypt_utils.h"
23 #include "crypt_errno.h"
24 #include "ecc_local.h"
25 
BN_IsZeroOrOne(const BN_BigNum * bn)26 static bool BN_IsZeroOrOne(const BN_BigNum *bn)
27 {
28     return (BN_IsZero(bn) || BN_IsOne(bn));
29 }
30 
ECP_PointAtInfinity(const ECC_Para * para,const ECC_Point * pt)31 int32_t ECP_PointAtInfinity(const ECC_Para *para, const ECC_Point *pt)
32 {
33     if (para == NULL || pt == NULL) {
34         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
35         return CRYPT_NULL_INPUT;
36     }
37     if (para->id != pt->id) {
38         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
39         return CRYPT_ECC_POINT_ERR_CURVE_ID;
40     }
41     // If z is 0, the point is the infinite point (0 point).
42     if (BN_IsZero(pt->z)) {
43         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
44         return CRYPT_ECC_POINT_AT_INFINITY;
45     }
46     return CRYPT_SUCCESS;
47 }
48 
49 // Check whether the point is on the curve.
ECP_PointOnCurve(const ECC_Para * para,const ECC_Point * pt)50 int32_t ECP_PointOnCurve(const ECC_Para *para, const ECC_Point *pt)
51 {
52     int32_t ret = 0;
53     uint32_t nistList[] = {CRYPT_ECC_NISTP224, CRYPT_ECC_NISTP256, CRYPT_ECC_NISTP384, CRYPT_ECC_NISTP521};
54     ret = ECP_PointAtInfinity(para, pt);
55     if (ret != CRYPT_SUCCESS) {
56         return ret;
57     }
58     // Do not check the point on the Jacobian coordinate system.
59     if (!BN_IsOne(pt->z)) {
60         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_NOT_AFFINE);
61         return CRYPT_ECC_POINT_NOT_AFFINE;
62     }
63 
64     uint32_t bits = BN_Bits(para->p);
65     BN_Optimizer *opt = BN_OptimizerCreate();
66     BN_BigNum *y = BN_Create(bits);
67     BN_BigNum *x = BN_Create(bits);
68     BN_BigNum *dupA = BN_Dup(para->a);
69     BN_BigNum *dupB = BN_Dup(para->b);
70     if (opt == NULL || x == NULL || y == NULL || dupA == NULL || dupB == NULL) {
71         ret = CRYPT_MEM_ALLOC_FAIL;
72         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
73         goto ERR;
74     }
75     if (para->method->bnMontDec != NULL) {
76         para->method->bnMontDec(dupA, para->montP);
77         para->method->bnMontDec(dupB, para->montP);
78     }
79     GOTO_ERR_IF(BN_ModSqr(x, pt->x, para->p, opt), ret); // x^2
80     GOTO_ERR_IF(BN_ModMul(x, x, pt->x, para->p, opt), ret); // x^3
81     if (ParamIdIsValid(para->id, nistList, sizeof(nistList) / sizeof(nistList[0]))) {
82         // Currently, only the NIST curve is supported(calculating x^3 - 3x).
83         // Other curves need to be expanded in the future.
84         GOTO_ERR_IF(BN_ModSub(x, x, pt->x, para->p, opt), ret);
85         GOTO_ERR_IF(BN_ModSub(x, x, pt->x, para->p, opt), ret);
86         GOTO_ERR_IF(BN_ModSub(x, x, pt->x, para->p, opt), ret); //  x^3 - 3x
87     } else {
88         // General implementation
89         GOTO_ERR_IF(BN_ModMul(y, dupA, pt->x, para->p, opt), ret);
90         GOTO_ERR_IF(BN_ModAdd(x, x, y, para->p, opt), ret); //  x^3 + ax
91     }
92 
93     GOTO_ERR_IF(BN_ModAdd(x, x, dupB, para->p, opt), ret); //  x^3 - 3x + b
94     GOTO_ERR_IF(BN_ModSqr(y, pt->y, para->p, opt), ret); // y^2
95     if (BN_Cmp(x, y) != 0) {
96         ret = CRYPT_ECC_POINT_NOT_ON_CURVE;
97         BSL_ERR_PUSH_ERROR(ret);
98     }
99 ERR:
100     BN_Destroy(x);
101     BN_Destroy(y);
102     BN_Destroy(dupA);
103     BN_Destroy(dupB);
104     BN_OptimizerDestroy(opt);
105     return ret;
106 }
107 
ECP_Point2Affine(const ECC_Para * para,ECC_Point * r,const ECC_Point * pt)108 int32_t ECP_Point2Affine(const ECC_Para *para, ECC_Point *r, const ECC_Point *pt)
109 {
110     if (para == NULL || r == NULL || pt == NULL) {
111         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
112         return CRYPT_NULL_INPUT;
113     }
114     if (para->id != pt->id || para->id != r->id) {
115         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
116         return CRYPT_ECC_POINT_ERR_CURVE_ID;
117     }
118     if (BN_IsZero(pt->z)) {
119         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
120         return CRYPT_ECC_POINT_AT_INFINITY;
121     }
122     if (BN_IsOne(pt->z)) {
123         return ECC_CopyPoint(r, pt);
124     }
125     int32_t ret;
126     uint32_t bits = BN_Bits(para->p);
127     BN_Optimizer *opt = BN_OptimizerCreate();
128     BN_BigNum *zz = BN_Create(bits);
129     BN_BigNum *inv = BN_Create(bits);
130     if (opt == NULL || zz == NULL || inv == NULL) {
131         ret = CRYPT_MEM_ALLOC_FAIL;
132         BSL_ERR_PUSH_ERROR(ret);
133         goto ERR;
134     }
135     GOTO_ERR_IF(BN_ModInv(inv, pt->z, para->p, opt), ret);
136     GOTO_ERR_IF(BN_ModSqr(zz, inv, para->p, opt), ret);
137 
138     GOTO_ERR_IF(BN_ModMul(r->x, pt->x, zz, para->p, opt), ret);
139 
140     GOTO_ERR_IF(BN_ModMul(zz, zz, inv, para->p, opt), ret);
141     GOTO_ERR_IF(BN_ModMul(r->y, pt->y, zz, para->p, opt), ret);
142 
143     GOTO_ERR_IF(BN_SetLimb(r->z, 1), ret);
144 ERR:
145     BN_Destroy(zz);
146     BN_Destroy(inv);
147     BN_OptimizerDestroy(opt);
148     return ret;
149 }
150 
Points2AffineParaCheck(const ECC_Para * para,ECC_Point * pt[],uint32_t ptNums)151 static int32_t Points2AffineParaCheck(const ECC_Para *para, ECC_Point *pt[], uint32_t ptNums)
152 {
153     if (para == NULL || pt == NULL) {
154         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
155         return CRYPT_NULL_INPUT;
156     }
157     if (ptNums == 0 || ptNums > PRE_COMPUTE_MAX_TABLELEN) {
158         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_WINDOW_TOO_MAX);
159         return CRYPT_ECC_POINT_WINDOW_TOO_MAX;
160     }
161     if (BN_IsZero(pt[0]->z)) {
162         // If the first point is an infinite point, exit directly.
163         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
164         return CRYPT_ECC_POINT_AT_INFINITY;
165     }
166     // Check whether the point ID matches.
167     uint32_t i;
168     for (i = 0; i < ptNums; i++) {
169         if (para->id != pt[i]->id) {
170             BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
171             return CRYPT_ECC_POINT_ERR_CURVE_ID;
172         }
173     }
174     return CRYPT_SUCCESS;
175 }
176 
Points2AffineCreatTmpData(BN_BigNum * pt[PRE_COMPUTE_MAX_TABLELEN],uint32_t ptNums,BN_BigNum ** inv,BN_Optimizer ** opt,const BN_BigNum * p)177 static int32_t Points2AffineCreatTmpData(BN_BigNum *pt[PRE_COMPUTE_MAX_TABLELEN], uint32_t ptNums,
178     BN_BigNum **inv, BN_Optimizer **opt, const BN_BigNum *p)
179 {
180     uint32_t bits = BN_Bits(p);
181     *opt = BN_OptimizerCreate();
182     *inv = BN_Create(bits);
183     if (*opt == NULL || *inv == NULL) {
184         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
185         return CRYPT_MEM_ALLOC_FAIL;
186     }
187     uint32_t i;
188     // Apply for pre-calculation table data.
189     for (i = 0; i < ptNums; i++) {
190         pt[i] = BN_Create(bits);
191         if (pt[i] == NULL) {
192             BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
193             return CRYPT_MEM_ALLOC_FAIL;
194         }
195     }
196     return CRYPT_SUCCESS;
197 }
198 
Points2AffineDestroyTmpData(BN_BigNum * pt[PRE_COMPUTE_MAX_TABLELEN],uint32_t ptNums,BN_BigNum * inv,BN_Optimizer * opt)199 static void Points2AffineDestroyTmpData(BN_BigNum *pt[PRE_COMPUTE_MAX_TABLELEN], uint32_t ptNums,
200     BN_BigNum *inv, BN_Optimizer *opt)
201 {
202     for (uint32_t i = 0; i < ptNums; i++) {
203         BN_Destroy(pt[i]);
204     }
205     BN_Destroy(inv);
206     BN_OptimizerDestroy(opt);
207 }
208 
209 // Multiple points are converted to the affine coordinate system. pt[0] cannot be infinite.
ECP_Points2Affine(const ECC_Para * para,ECC_Point * pt[],uint32_t ptNums)210 int32_t ECP_Points2Affine(const ECC_Para *para, ECC_Point *pt[], uint32_t ptNums)
211 {
212     int32_t ret = Points2AffineParaCheck(para, pt, ptNums);
213     if (ret != CRYPT_SUCCESS) {
214         return ret;
215     }
216     BN_BigNum *t[PRE_COMPUTE_MAX_TABLELEN] = { 0 }; // pre-calculation table
217     BN_BigNum *inv = NULL;
218     BN_Optimizer *opt = NULL;
219     GOTO_ERR_IF(Points2AffineCreatTmpData(t, ptNums, &inv, &opt, para->p), ret);
220     // t[i] = z[0] * z[1]* ... * z[i]
221     GOTO_ERR_IF(BN_Copy(t[0], pt[0]->z), ret);
222     uint32_t i;
223     for (i = 1; i < ptNums; i++) {
224         if (BN_IsZeroOrOne(pt[i]->z)) {
225             GOTO_ERR_IF(BN_Copy(t[i], t[i - 1]), ret); // copy last one
226             continue;
227         }
228         GOTO_ERR_IF(BN_ModMul(t[i], t[i - 1], pt[i]->z, para->p, opt), ret);
229     }
230 
231     // inv = 1 / (z[0] * z[1] * .... * z[ptNums - 1])
232     GOTO_ERR_IF(BN_ModInv(inv, t[ptNums - 1], para->p, opt), ret);
233 
234     // t[i] = 1/z[i]
235     for (i = ptNums - 1; i > 0; i--) {
236         if (BN_IsZeroOrOne(pt[i]->z)) {
237             continue;
238         }
239         // t[i] *= z[0]*z[1]*...*z[i - 1] = 1/z[i]
240         GOTO_ERR_IF(BN_ModMul(t[i], t[i - 1], inv, para->p, opt), ret);
241         // inv *= z[i] = 1/(z[0]*z[1]*...z[i - 1])
242         GOTO_ERR_IF(BN_ModMul(inv, pt[i]->z, inv, para->p, opt), ret);
243     }
244     GOTO_ERR_IF(BN_Copy(t[0], inv), ret); // inv = 1/z[0]
245 
246     // Calculate x = x/(z^2); y = y/(z^3)
247     for (i = 0; i < ptNums; i++) {
248         if (BN_IsZeroOrOne(pt[i]->z)) {
249             continue;
250         }
251         GOTO_ERR_IF(ECP_Point2AffineWithInv(para, pt[i], pt[i], t[i]), ret);
252     }
253 ERR:
254     Points2AffineDestroyTmpData(t, ptNums, inv, opt);
255     return ret;
256 }
257 
258 // consttime
ECP_PointCopyWithMask(ECC_Point * r,const ECC_Point * a,const ECC_Point * b,BN_UINT mask)259 static int32_t ECP_PointCopyWithMask(ECC_Point *r, const ECC_Point *a, const ECC_Point *b, BN_UINT mask)
260 {
261     int32_t ret;
262     GOTO_ERR_IF(BN_CopyWithMask(r->x, a->x, b->x, mask), ret);
263     GOTO_ERR_IF(BN_CopyWithMask(r->y, a->y, b->y, mask), ret);
264     GOTO_ERR_IF(BN_CopyWithMask(r->z, a->z, b->z, mask), ret);
265 ERR:
266     return ret;
267 }
268 
ECP_PointMul(ECC_Para * para,ECC_Point * r,const BN_BigNum * k,const ECC_Point * pt)269 int32_t ECP_PointMul(ECC_Para *para,  ECC_Point *r, const BN_BigNum *k, const ECC_Point *pt)
270 {
271     if (para == NULL || r == NULL || k == NULL) {
272         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
273         return CRYPT_NULL_INPUT;
274     }
275     if ((para->id != r->id) || ((pt != NULL) && (para->id != pt->id))) {
276         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
277         return CRYPT_ECC_POINT_ERR_CURVE_ID;
278     }
279     if (pt != NULL && BN_IsZero(pt->z)) {
280         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
281         return CRYPT_ECC_POINT_AT_INFINITY;
282     }
283     if (BN_IsZero(k)) {
284         BN_Zeroize(r->z);
285         return CRYPT_SUCCESS;
286     }
287     if (BN_Cmp(k, para->n) == 0 && pt != NULL) {
288         // In this case, the consttime calculation is not required
289         // for checking whether the public key information is valid.
290         return ECP_PointMulFast(para, r, para->n, pt);
291     }
292     uint32_t i;
293     int32_t ret;
294     BN_UINT mask;
295     uint32_t bits;
296     ECC_Point *base = (pt != NULL) ? ECC_DupPoint(pt) : ECC_GetGFromPara(para);
297     ECC_Point *t = ECC_NewPoint(para);
298     BN_Optimizer *opt = BN_OptimizerCreate();
299     if (base == NULL || t == NULL || opt == NULL) {
300         ret = CRYPT_MEM_ALLOC_FAIL;
301         BSL_ERR_PUSH_ERROR(ret);
302         goto ERR;
303     }
304     // Convert base to affine.
305     GOTO_ERR_IF(ECP_Point2Affine(para, base, base), ret);
306     // Add salt to prevent side channels.
307     GOTO_ERR_IF(ECC_PointToMont(para, base, opt), ret);
308     GOTO_ERR_IF(ECC_CopyPoint(r, base), ret);
309     GOTO_ERR_IF(ECC_PointBlind(para, r), ret);
310     bits = BN_Bits(k);
311     for (i = bits - 1; i > 0; i--) {
312         GOTO_ERR_IF(para->method->pointDouble(para, r, r), ret);
313         GOTO_ERR_IF(para->method->pointAddAffine(para, t, r, base), ret);
314         mask = BN_GetBit(k, i - 1) ? 0 : BN_MASK;
315         // The last bit must be 1, and r must be updated to the latest data.
316         GOTO_ERR_IF(ECP_PointCopyWithMask(r, t, r, mask), ret);
317     }
318     ECC_PointFromMont(para, r);
319 ERR:
320     ECC_FreePoint(t);
321     ECC_FreePoint(base);
322     BN_OptimizerDestroy(opt);
323     return ret;
324 }
325 
326 // Generate a BigNum equal to (p + 1) / 2
ECP_HalfPGet(const BN_BigNum * p)327 BN_BigNum *ECP_HalfPGet(const BN_BigNum *p)
328 {
329     int32_t ret;
330     uint32_t bits = BN_Bits(p);
331     BN_BigNum *halfP = BN_Create(bits + 1);
332     if (halfP == NULL) {
333         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
334         return NULL;
335     }
336     GOTO_ERR_IF_EX(BN_AddLimb(halfP, p, 1), ret);
337     GOTO_ERR_IF_EX(BN_Rshift(halfP, halfP, 1), ret);
338     return halfP;
339 ERR:
340     BN_Destroy(halfP);
341     return NULL;
342 }
343 
344 // The z coordinate of point pt multiplied by z.
ECP_Point2AffineWithInv(const ECC_Para * para,ECC_Point * r,const ECC_Point * pt,const BN_BigNum * inv)345 int32_t ECP_Point2AffineWithInv(const ECC_Para *para, ECC_Point *r, const ECC_Point *pt, const BN_BigNum *inv)
346 {
347     if (para == NULL || r == NULL || pt == NULL || inv == NULL) {
348         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
349         return CRYPT_NULL_INPUT;
350     }
351     if (para->id != pt->id || para->id != r->id) {
352         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
353         return CRYPT_ECC_POINT_ERR_CURVE_ID;
354     }
355     if (BN_IsZero(pt->z)) {
356         // Infinite point multiplied by z is meaningless.
357         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
358         return CRYPT_ECC_POINT_AT_INFINITY;
359     }
360     BN_Optimizer *opt = BN_OptimizerCreate();
361     if (opt == NULL) {
362         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
363         return CRYPT_MEM_ALLOC_FAIL;
364     }
365     int32_t ret;
366     GOTO_ERR_IF(BN_ModSqr(r->z, inv, para->p, opt), ret);            // z = inv^2
367     GOTO_ERR_IF(BN_ModMul(r->x, pt->x, r->z, para->p, opt), ret);    // x = x * (inv^2)
368     GOTO_ERR_IF(BN_ModMul(r->y, pt->y, inv, para->p, opt), ret);
369     GOTO_ERR_IF(BN_ModMul(r->y, r->y, r->z, para->p, opt), ret);     // y = y * (inv^3)
370     GOTO_ERR_IF(BN_SetLimb(r->z, 1), ret);                           // z = 1
371 ERR:
372     BN_OptimizerDestroy(opt);
373     return ret;
374 }
375 
376 // Convert (x, y, z) to (x/z0^2, y/z0^3, z*z0)
ECP_PointJacMulZ(const ECC_Para * para,ECC_Point * pt,const BN_BigNum * z,BN_Optimizer * opt)377 static int32_t ECP_PointJacMulZ(const ECC_Para *para, ECC_Point *pt, const BN_BigNum *z, BN_Optimizer *opt)
378 {
379     if (BN_IsZero(pt->z)) {
380         // Infinite point multiplied by z is meaningless.
381         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
382         return CRYPT_ECC_POINT_AT_INFINITY;
383     }
384     uint32_t bits = BN_Bits(para->p);
385     BN_BigNum *t = BN_Create(bits);
386     if (t == NULL) {
387         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
388         return CRYPT_MEM_ALLOC_FAIL;
389     }
390     int32_t ret;
391     GOTO_ERR_IF(BN_ModMul(pt->z, pt->z, z, para->p, opt), ret);  // z = z * z0
392     GOTO_ERR_IF(BN_ModMul(pt->y, pt->y, z, para->p, opt), ret);  // y = y * z0
393     GOTO_ERR_IF(BN_ModSqr(t, z, para->p, opt), ret);             // t = z0^2
394     GOTO_ERR_IF(BN_ModMul(pt->x, pt->x, t, para->p, opt), ret);  // x = x * (z0^2)
395     GOTO_ERR_IF(BN_ModMul(pt->y, pt->y, t, para->p, opt), ret);  // y = y * (z0^3)
396 ERR:
397     BN_Destroy(t);
398     return ret;
399 }
400 
401 /*
402  * relate to the paper "Resistance against Differential Power Analysis for Elliptic Curve Cryptosystems"
403  * chapter 5.3 Third Countermeasure: Randomized Projective Coordinates
404  * reference: http://www.crypto-uni.lu/jscoron/publications/dpaecc.pdf
405  */
ECC_PointBlind(const ECC_Para * para,ECC_Point * pt)406 int32_t ECC_PointBlind(const ECC_Para *para, ECC_Point *pt)
407 {
408     if (para == NULL || pt == NULL) {
409         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
410         return CRYPT_NULL_INPUT;
411     }
412     if (para->id != pt->id) {
413         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
414         return CRYPT_ECC_POINT_ERR_CURVE_ID;
415     }
416     int32_t ret;
417     uint32_t bits = BN_Bits(para->p);
418     BN_BigNum *blind = BN_Create(bits);
419     BN_Optimizer *opt = BN_OptimizerCreate();
420     if (blind == NULL || opt == NULL) {
421         ret = CRYPT_MEM_ALLOC_FAIL;
422         BSL_ERR_PUSH_ERROR(ret);
423         goto ERR;
424     }
425     // Generate random numbers to randomize z.
426     GOTO_ERR_IF(BN_RandRangeEx(para->libCtx, blind, para->p), ret);
427     if (BN_IsZero(blind)) {
428         ret = CRYPT_ECC_POINT_BLIND_WITH_ZERO;
429         BSL_ERR_PUSH_ERROR(ret);
430         goto ERR;
431     }
432     GOTO_ERR_IF_EX(ECP_PointJacMulZ(para, pt, blind, opt), ret);
433 ERR:
434     BN_Destroy(blind);
435     BN_OptimizerDestroy(opt);
436     return ret;
437 }
438 
ECP_PointCmp(const ECC_Para * para,const ECC_Point * a,const ECC_Point * b)439 int32_t ECP_PointCmp(const ECC_Para *para, const ECC_Point *a, const ECC_Point *b)
440 {
441     if (para == NULL || a == NULL || b == NULL) {
442         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
443         return CRYPT_NULL_INPUT;
444     }
445     if (para->id != a->id || para->id != b->id) {
446         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
447         return CRYPT_ECC_POINT_ERR_CURVE_ID;
448     }
449     // If both points are infinite points, equality is returned.
450     if (BN_IsZero(a->z) && BN_IsZero(b->z)) {
451         return CRYPT_SUCCESS;
452     }
453     if (BN_IsZero(a->z) || BN_IsZero(b->z)) {
454         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_NOT_EQUAL);
455         return CRYPT_ECC_POINT_NOT_EQUAL;
456     }
457 
458     int32_t ret;
459     BN_Optimizer *opt = BN_OptimizerCreate();
460     ECC_Point *az = ECC_DupPoint(a);
461     ECC_Point *bz = ECC_DupPoint(b);
462     if (opt == NULL || az == NULL || bz == NULL) {
463         ret = CRYPT_MEM_ALLOC_FAIL;
464         BSL_ERR_PUSH_ERROR(ret);
465         goto ERR;
466     }
467     // Transfer a and b to the same z.
468     GOTO_ERR_IF(ECP_PointJacMulZ(para, az, b->z, opt), ret);
469     GOTO_ERR_IF(ECP_PointJacMulZ(para, bz, a->z, opt), ret);
470     if ((BN_Cmp(az->x, bz->x) != 0) || (BN_Cmp(az->y, bz->y) != 0)) {
471         ret = CRYPT_ECC_POINT_NOT_EQUAL;
472         BSL_ERR_PUSH_ERROR(ret);
473     }
474 ERR:
475     ECC_FreePoint(az);
476     ECC_FreePoint(bz);
477     BN_OptimizerDestroy(opt);
478     return ret;
479 }
480 
ECP_PointCopy(const ECC_Para * para,ECC_Point * a,const ECC_Point * b)481 int32_t ECP_PointCopy(const ECC_Para *para, ECC_Point *a, const ECC_Point *b)
482 {
483     (void)para;
484     int32_t ret;
485 
486     a->id = b->id;
487     GOTO_ERR_IF(BN_Copy(a->x, b->x), ret);
488     GOTO_ERR_IF(BN_Copy(a->y, b->y), ret);
489     GOTO_ERR_IF(BN_Copy(a->z, b->z), ret);
490 ERR:
491     return ret;
492 }
493 
494 // Cartesian coordinate point inversion.
ECP_PointInvertAtAffine(const ECC_Para * para,ECC_Point * r,const ECC_Point * a)495 int32_t ECP_PointInvertAtAffine(const ECC_Para *para, ECC_Point *r, const ECC_Point *a)
496 {
497     if (para == NULL || r == NULL || a == NULL) {
498         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
499         return CRYPT_NULL_INPUT;
500     }
501     if (para->id != r->id || para->id != a->id) {
502         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
503         return CRYPT_ECC_POINT_ERR_CURVE_ID;
504     }
505     if (BN_IsZero(a->z)) {
506         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
507         return CRYPT_ECC_POINT_AT_INFINITY;
508     }
509     int32_t ret;
510     GOTO_ERR_IF(ECC_CopyPoint(r, a), ret);
511     GOTO_ERR_IF(BN_Sub(r->y, para->p, r->y), ret);
512 ERR:
513     return ret;
514 }
515 
516 // The default ECP window length is 5 bits and only odd points are calculated.
517 #define WINDOW_TABLE_SIZE (PRE_COMPUTE_MAX_TABLELEN >> 1)
518 
ECP_PointPreCompute(const ECC_Para * para,ECC_Point * windows[],const ECC_Point * pt)519 static int32_t ECP_PointPreCompute(const ECC_Para *para, ECC_Point *windows[], const ECC_Point *pt)
520 {
521     int32_t ret;
522     ECC_Point *doubleP = ECC_NewPoint(para);
523     windows[0] = ECC_DupPoint(pt);
524     BN_Optimizer *opt = NULL;
525     uint32_t i;
526     for (i = 1; i < WINDOW_TABLE_SIZE; i++) {
527         windows[i] = ECC_NewPoint(para);
528     }
529     if (doubleP == NULL) {
530         ret = CRYPT_MEM_ALLOC_FAIL;
531         BSL_ERR_PUSH_ERROR(ret);
532         goto ERR;
533     }
534     for (i = 0; i < WINDOW_TABLE_SIZE; i++) {
535         if (windows[i] == NULL) {
536             ret = CRYPT_MEM_ALLOC_FAIL;
537             BSL_ERR_PUSH_ERROR(ret);
538             goto ERR;
539         }
540     }
541     opt = BN_OptimizerCreate();
542     if (opt == NULL) {
543         ret = CRYPT_MEM_ALLOC_FAIL;
544         BSL_ERR_PUSH_ERROR(ret);
545         goto ERR;
546     }
547     GOTO_ERR_IF(ECC_PointToMont(para, windows[0], opt), ret);
548     GOTO_ERR_IF(para->method->pointDouble(para, doubleP, windows[0]), ret);
549     for (i = 1; i < (WINDOW_TABLE_SIZE >> 1); i++) {
550         GOTO_ERR_IF(para->method->pointAdd(para, windows[i], windows[i - 1], doubleP), ret);
551     }
552     for (i = WINDOW_TABLE_SIZE >> 1; i < WINDOW_TABLE_SIZE; i++) {
553         GOTO_ERR_IF(ECP_PointInvertAtAffine(para, windows[i], windows[i - (WINDOW_TABLE_SIZE >> 1)]), ret);
554     }
555     BN_OptimizerDestroy(opt);
556     ECC_FreePoint(doubleP);
557     return ret;
558 ERR:
559     for (i = 0; i < WINDOW_TABLE_SIZE; i++) {
560         ECC_FreePoint(windows[i]);
561         windows[i] = NULL;
562     }
563     BN_OptimizerDestroy(opt);
564     ECC_FreePoint(doubleP);
565     return ret;
566 }
567 
ECP_ParaPrecompute(ECC_Para * para)568 static int32_t ECP_ParaPrecompute(ECC_Para *para)
569 {
570     if (para->tableG[0] != NULL) {
571         // The pre-computation table already exists.
572         return CRYPT_SUCCESS;
573     }
574     int32_t ret;
575     ECC_Point *pt = ECC_GetGFromPara(para);
576     if (pt == NULL) {
577         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
578         return CRYPT_MEM_ALLOC_FAIL;
579     }
580     GOTO_ERR_IF(ECP_PointPreCompute(para, para->tableG, pt), ret);
581 ERR:
582     ECC_FreePoint(pt);
583     return ret;
584 }
585 
ECC_ReCodeFree(ReCodeData * code)586 void ECC_ReCodeFree(ReCodeData *code)
587 {
588     if (code == NULL) {
589         return;
590     }
591     BSL_SAL_FREE(code->num); // The encoded data is insensitive and does not need to be set to 0.
592     BSL_SAL_FREE(code->wide);
593     BSL_SAL_FREE(code);
594 }
595 
WinCodeNew(uint32_t len)596 static ReCodeData *WinCodeNew(uint32_t len)
597 {
598     ReCodeData *code = BSL_SAL_Malloc(sizeof(ReCodeData));
599     if (code == NULL) {
600         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
601         return NULL;
602     }
603     code->num = BSL_SAL_Malloc(len * sizeof(int8_t));
604     code->wide = BSL_SAL_Malloc(len * sizeof(uint32_t));
605     if (code->num == NULL || code->wide == NULL) {
606         ECC_ReCodeFree(code);
607         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
608         return NULL;
609     }
610     return code;
611 }
612 
613 // Shift the recoded data. If the shift fails, release the code data.
RecodeKMove(ReCodeData * code,uint32_t len,uint32_t offset)614 static int32_t RecodeKMove(ReCodeData *code, uint32_t len, uint32_t offset)
615 {
616     // Data shift. The value assignment starts from the tail and moves the data to the left to start position.
617     if (memmove_s(code->num, len * sizeof(int8_t), &(code->num[offset]), code->size * sizeof(int8_t)) != EOK ||
618         memmove_s(code->wide, len * sizeof(uint32_t), &(code->wide[offset]), code->size * sizeof(uint32_t)) != EOK) {
619         ECC_ReCodeFree(code);
620         BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
621         return CRYPT_SECUREC_FAIL;
622     }
623     return CRYPT_SUCCESS;
624 }
625 
626 // Recode scalar data, remove the most significant bit 1 of the data in the window.
ECC_ReCodeK(const BN_BigNum * k,uint32_t window)627 ReCodeData *ECC_ReCodeK(const BN_BigNum *k, uint32_t window)
628 {
629     if (k == NULL || window == 0) {
630         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
631         return NULL;
632     }
633     int8_t max = (1 << window);
634     uint32_t bits = BN_Bits(k);
635     uint32_t len = (bits / window) + 1;
636     ReCodeData *code = WinCodeNew(len);
637     if (code == NULL) {
638         // The internal function WinCodeNew has executed push_err.
639         return NULL;
640     }
641     uint32_t offset = len;
642     uint32_t base = 0;
643     bool carry = false;
644     uint32_t lastWide = 0;
645     while (base != bits) {
646         offset--;
647         // Find the start bit of the new item.
648         while (BN_GetBit(k, base) == carry) {
649             base++;
650             lastWide++;
651         }
652         int8_t num = 0;
653         uint32_t shift = 0;
654         // Obtain the item of the window length.
655         while ((shift < window) && (base != bits)) {
656             int8_t add = (((BN_GetBit(k, base) ? 1 : 0)) << shift);
657             num += add;
658             base++;
659             shift++;
660         }
661         // If there is a carry, perform carry processing.
662         num += (carry ? 1 : 0);
663         // Refresh carry.
664         carry = num >= (max / 2); // Check whether the value >= (max/2). If yes, convert the value.
665         // If the value of a new carry item exists, convert it to -(2^win - num)
666         num = carry ? (-(max - num)) : num;
667         code->num[offset] = num;
668         code->wide[offset] = lastWide;
669         lastWide = shift;
670     }
671     // If carry information exists, store data 1 in the most significant bit.
672     if (carry) {
673         offset--;
674         code->num[offset] = 1;
675         code->wide[offset] = lastWide;
676     }
677     code->baseBits = carry ? bits : (bits - lastWide);
678     code->size = len - offset;
679     // Data shift. The value assignment starts from the tail and moves the data to the left to start position.
680     if (RecodeKMove(code, len, offset) != CRYPT_SUCCESS) {
681         // If the operation fails, the RecodeKMove releases the code data.
682         return NULL;
683     }
684     return code;
685 }
686 
687 // Layout format of the pre-computation table.
688 // This macro is used to convert values into corresponding offsets.
689 // layout rules (1, 3, 5, 7... 15, -1, -3, ... -15)
690 #define NUMTOOFFSET(num) (((num) < 0) ? (WINDOW_TABLE_SIZE / 2 - 1 - (((num) - 1) / 2)) : (((num) - 1) / 2))
691 
692 typedef struct {
693     uint32_t baseBits;
694     uint32_t bit;
695     uint32_t bit1;
696     uint32_t bit2;
697     uint32_t offsetK1;
698     uint32_t offsetK2;
699     ReCodeData *codeK1;
700     ReCodeData *codeK2;
701 } MulAddOffData;
702 
GetFirstData(const ECC_Para * para,ECC_Point * t,MulAddOffData * offData,ECC_Point ** windowsP)703 static int32_t GetFirstData(const ECC_Para *para, ECC_Point *t, MulAddOffData *offData,
704     ECC_Point **windowsP)
705 {
706     int32_t ret;
707     ECC_Point *const *windowsG = para->tableG;
708     // Obtain the maximum start offset of the first item.
709     offData->baseBits = (offData->codeK1->baseBits > offData->codeK2->baseBits) ?
710         offData->codeK1->baseBits : offData->codeK2->baseBits;
711     // If they are equal, the initial value is the sum of the two first items.
712     // Otherwise, the initial value is the item with a larger offset among the two items.
713     if (offData->codeK1->baseBits == offData->codeK2->baseBits) {
714         int8_t offset1 = NUMTOOFFSET(offData->codeK1->num[offData->offsetK1]);
715         int8_t offset2 = NUMTOOFFSET(offData->codeK2->num[offData->offsetK2]);
716         GOTO_ERR_IF(para->method->pointAdd(para, t, windowsG[offset1], windowsP[offset2]), ret);
717         offData->offsetK1++;
718         offData->offsetK2++;
719         offData->bit1 = offData->codeK1->wide[offData->offsetK1 - 1];
720         offData->bit2 = offData->codeK2->wide[offData->offsetK2 - 1];
721     } else if (offData->codeK1->baseBits > offData->codeK2->baseBits) {
722         int8_t offset = NUMTOOFFSET(offData->codeK1->num[offData->offsetK1]);
723         GOTO_ERR_IF(ECC_CopyPoint(t, windowsG[offset]), ret);
724         offData->offsetK1++;
725         offData->bit1 = offData->codeK1->wide[offData->offsetK1 - 1];
726         offData->bit2 = offData->baseBits - offData->codeK2->baseBits;
727     } else {
728         int8_t offset = NUMTOOFFSET(offData->codeK2->num[offData->offsetK2]);
729         GOTO_ERR_IF(ECC_CopyPoint(t, windowsP[offset]), ret);
730         offData->offsetK2++;
731         offData->bit1 = offData->baseBits - offData->codeK1->baseBits;
732         offData->bit2 = offData->codeK2->wide[offData->offsetK2 - 1];
733     }
734 ERR:
735     return ret;
736 }
737 
PointMulAddParaCheck(const ECC_Para * para,const ECC_Point * r,const BN_BigNum * k1,const BN_BigNum * k2,const ECC_Point * pt)738 static int32_t PointMulAddParaCheck(const ECC_Para *para, const ECC_Point *r, const BN_BigNum *k1,
739     const BN_BigNum *k2, const ECC_Point *pt)
740 {
741     if (para == NULL || r == NULL || k1 == NULL || k2 == NULL || pt == NULL) {
742         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
743         return CRYPT_NULL_INPUT;
744     }
745     if ((para->id != r->id) || (para->id != pt->id)) {
746         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
747         return CRYPT_ECC_POINT_ERR_CURVE_ID;
748     }
749     if (BN_IsZero(pt->z)) {
750         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
751         return CRYPT_ECC_POINT_AT_INFINITY;
752     }
753     return CRYPT_SUCCESS;
754 }
755 
756 // NotConstTime r = order*pt
ECP_PointMulFast(ECC_Para * para,ECC_Point * r,const BN_BigNum * k,const ECC_Point * pt)757 int32_t ECP_PointMulFast(ECC_Para *para, ECC_Point *r, const BN_BigNum *k, const ECC_Point *pt)
758 {
759     if (para == NULL || r == NULL || k == NULL) {
760         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
761         return CRYPT_NULL_INPUT;
762     }
763     if ((para->id != r->id) || ((pt != NULL) && (para->id != pt->id))) {
764         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
765         return CRYPT_ECC_POINT_ERR_CURVE_ID;
766     }
767     if (BN_IsZero(k)) {
768         BN_Zeroize(r->z);
769         return CRYPT_SUCCESS;
770     }
771     int32_t ret;
772     ReCodeData *codeK = NULL;
773     int8_t offset;
774 
775     ECC_Point *windowsP[WINDOW_TABLE_SIZE] = { 0 };
776     ECC_Point **windows = NULL;
777     if (pt == NULL) {
778         GOTO_ERR_IF(ECP_ParaPrecompute(para), ret);
779         windows = para->tableG;
780     } else {
781         GOTO_ERR_IF(ECP_PointPreCompute(para, windowsP, pt), ret);
782         windows = windowsP;
783     }
784 
785     codeK = ECC_ReCodeK(k, PRE_COMPUTE_WINDOW);
786     if (codeK == NULL) {
787         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
788         ret = CRYPT_MEM_ALLOC_FAIL;
789         goto ERR;
790     }
791     offset = NUMTOOFFSET(codeK->num[0]);
792     GOTO_ERR_IF(ECC_CopyPoint(r, windows[offset]), ret);
793     GOTO_ERR_IF(para->method->pointMultDouble(para, r, r, codeK->wide[0]), ret);
794     for (uint32_t i = 1; i < codeK->size; i++) {
795         offset = NUMTOOFFSET(codeK->num[i]);
796         GOTO_ERR_IF(para->method->pointAdd(para, r, r, windows[offset]), ret);
797         GOTO_ERR_IF(para->method->pointMultDouble(para, r, r, codeK->wide[i]), ret);
798     }
799     ECC_PointFromMont(para, r);
800 ERR:
801     for (uint32_t i = 0; i < WINDOW_TABLE_SIZE; i++) {
802         // Clear the pre-computation table.
803         ECC_FreePoint(windowsP[i]);
804     }
805     ECC_ReCodeFree(codeK);
806     return ret;
807 }
808 
KZeroHandle(ECC_Para * para,ECC_Point * r,const BN_BigNum * k1,const BN_BigNum * k2,const ECC_Point * pt)809 static int32_t KZeroHandle(ECC_Para *para, ECC_Point *r, const BN_BigNum *k1,
810     const BN_BigNum *k2, const ECC_Point *pt)
811 {
812     if (BN_IsZero(k1) && BN_IsZero(k2)) {
813         // When k1 and k2 are both 0, the result is infinity.
814         BN_Zeroize(r->z);
815         return CRYPT_SUCCESS;
816     }
817     if (BN_IsZero(k1)) {
818         return ECP_PointMulFast(para, r, k2, pt);
819     }
820     // k2 is 0
821     return ECP_PointMulFast(para, r, k1, NULL);
822 }
823 
824 // wNaf NotConstTime
ECP_PointMulAdd(ECC_Para * para,ECC_Point * r,const BN_BigNum * k1,const BN_BigNum * k2,const ECC_Point * pt)825 int32_t ECP_PointMulAdd(ECC_Para *para, ECC_Point *r, const BN_BigNum *k1,
826     const BN_BigNum *k2, const ECC_Point *pt)
827 {
828     int32_t ret = PointMulAddParaCheck(para, r, k1, k2, pt);
829     if (ret != CRYPT_SUCCESS) {
830         return ret;
831     }
832     if (BN_IsZero(k1) || BN_IsZero(k2)) {
833         return KZeroHandle(para, r, k1, k2, pt);
834     }
835     MulAddOffData offData = { 0 };
836     ECC_Point *windowsP[WINDOW_TABLE_SIZE] = { 0 };
837     ECC_Point **windowsG = NULL;
838     GOTO_ERR_IF(ECP_ParaPrecompute(para), ret);
839     GOTO_ERR_IF(ECP_PointPreCompute(para, windowsP, pt), ret);
840     windowsG = para->tableG;
841     offData.codeK1 = ECC_ReCodeK(k1, PRE_COMPUTE_WINDOW);
842     offData.codeK2 = ECC_ReCodeK(k2, PRE_COMPUTE_WINDOW);
843     if (offData.codeK1 == NULL || offData.codeK2 == NULL) {
844         ret = CRYPT_MEM_ALLOC_FAIL;
845         BSL_ERR_PUSH_ERROR(ret);
846         goto ERR;
847     }
848     // Obtain the initial point data.
849     GOTO_ERR_IF(GetFirstData(para, r, &offData, windowsP), ret);
850 
851     while (offData.baseBits != 0) {
852         // Slide window
853         offData.bit1 = (offData.bit1 == 0) ? (offData.codeK1->wide[offData.offsetK1 - 1]) : (offData.bit1);
854         offData.bit2 = (offData.bit2 == 0) ? (offData.codeK2->wide[offData.offsetK2 - 1]) : (offData.bit2);
855         offData.bit = (offData.bit1 < offData.bit2) ? (offData.bit1) : (offData.bit2);
856         GOTO_ERR_IF(para->method->pointMultDouble(para, r, r, offData.bit), ret);
857         if (offData.bit == offData.bit1 && offData.offsetK1 < offData.codeK1->size) {
858             int8_t offset = NUMTOOFFSET(offData.codeK1->num[offData.offsetK1]);
859             GOTO_ERR_IF(para->method->pointAdd(para, r, r, windowsG[offset]), ret);
860             offData.offsetK1++;
861         }
862         if (offData.bit == offData.bit2 && offData.offsetK2 < offData.codeK2->size) {
863             int8_t offset = NUMTOOFFSET(offData.codeK2->num[offData.offsetK2]);
864             GOTO_ERR_IF(para->method->pointAdd(para, r, r, windowsP[offset]), ret);
865             offData.offsetK2++;
866         }
867         offData.bit1 -= offData.bit;
868         offData.bit2 -= offData.bit;
869         offData.baseBits -= offData.bit;
870     }
871     ECC_PointFromMont(para, r);
872 ERR:
873     for (uint32_t i = 0; i < WINDOW_TABLE_SIZE; i++) {
874         // Clear the pre-computation table.
875         ECC_FreePoint(windowsP[i]);
876     }
877     ECC_ReCodeFree(offData.codeK1);
878     ECC_ReCodeFree(offData.codeK2);
879     return ret;
880 }
881 
PointParaCheck(const ECC_Para * para,const ECC_Point * pt,int32_t format)882 static int32_t PointParaCheck(const ECC_Para *para, const ECC_Point *pt, int32_t format)
883 {
884     int32_t ret = ECP_PointAtInfinity(para, pt);
885     if (ret != CRYPT_SUCCESS) {
886         return ret;
887     }
888     if (format < CRYPT_POINT_COMPRESSED || format > CRYPT_POINT_HYBRID) {
889         BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_POINT_FORMAT);
890         return CRYPT_ECC_ERR_POINT_FORMAT;
891     }
892     return CRYPT_SUCCESS;
893 }
894 
EncodePointParaCheck(const ECC_Para * para,const ECC_Point * pt,const uint8_t * data,const uint32_t * dataLen,CRYPT_PKEY_PointFormat format)895 static int32_t EncodePointParaCheck(const ECC_Para *para, const ECC_Point *pt, const uint8_t *data,
896     const uint32_t *dataLen, CRYPT_PKEY_PointFormat format)
897 {
898     int32_t ret = PointParaCheck(para, pt, format);
899     if (ret != CRYPT_SUCCESS) {
900         return ret;
901     }
902 
903     if (data == NULL || dataLen == NULL) {
904         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
905         return CRYPT_NULL_INPUT;
906     }
907 
908     uint32_t curveBytes = BN_Bytes(para->p);
909     // Obtain the required buff length based on the compression format.
910     uint32_t needBytes = (format == CRYPT_POINT_COMPRESSED) ? (curveBytes + 1) : ((curveBytes << 1) + 1);
911     if (needBytes > *dataLen) {
912         BSL_ERR_PUSH_ERROR(CRYPT_ECC_BUFF_LEN_NOT_ENOUGH);
913         return CRYPT_ECC_BUFF_LEN_NOT_ENOUGH;
914     }
915     return CRYPT_SUCCESS;
916 }
917 
ECP_EncodePoint(const ECC_Para * para,ECC_Point * pt,uint8_t * data,uint32_t * dataLen,CRYPT_PKEY_PointFormat format)918 int32_t ECP_EncodePoint(const ECC_Para *para, ECC_Point *pt, uint8_t *data, uint32_t *dataLen,
919     CRYPT_PKEY_PointFormat format)
920 {
921     int32_t ret;
922     bool z = 0;
923     uint32_t bytes, off, lastLen, i, curveBytes;
924     GOTO_ERR_IF(EncodePointParaCheck(para, pt, data, dataLen, format), ret);
925     // Convert the point to affine.
926     GOTO_ERR_IF(para->method->point2Affine(para, pt, pt), ret);
927     z = BN_GetBit(pt->y, 0);
928     bytes = BN_Bytes(pt->x);
929     curveBytes = BN_Bytes(para->p);
930     off = curveBytes - bytes;
931     for (i = 0; i < off; i++) {
932         // Padded 0s to the most significant bits.
933         data[i + 1] = 0;
934     }
935     lastLen = *dataLen - off - 1;
936     GOTO_ERR_IF(BN_Bn2Bin(pt->x, &data[off + 1], &lastLen), ret);
937     /**
938      * ANS X9.62–2005 A.5.5
939      * If the compressed form is used PC is either 02 or 03.
940      * If the uncompressed form is used Verify that PC is 04.
941      * If the hybrid form is used Verify that PC is either 06 or 07
942     */
943     if (format == CRYPT_POINT_COMPRESSED) {
944         // Set the bit zP to be equal to 0 if PC = 02, or 1 if PC = 03.
945         data[0] = z ? 0x03 : 0x02;
946         *dataLen = curveBytes + 1;
947         return CRYPT_SUCCESS;
948     } else if (format == CRYPT_POINT_UNCOMPRESSED) {
949         data[0] = 0x04;
950     } else if (format == CRYPT_POINT_HYBRID) {
951         // Set the bit zP to be equal to 0 if PC = 06, or 1 if PC = 07.
952         data[0] = z ? 0x07 : 0x06;
953     }
954     bytes = BN_Bytes(pt->y);
955     off = curveBytes - bytes;
956     for (i = 0; i < off; i++) {
957         // Padded 0s to the most significant bits.
958         data[i + curveBytes + 1] = 0;
959     }
960     lastLen = *dataLen - off - curveBytes - 1;
961     GOTO_ERR_IF(BN_Bn2Bin(pt->y, &data[off + curveBytes + 1], &lastLen), ret);
962     *dataLen = (curveBytes << 1) + 1;
963 ERR:
964     return ret;
965 }
966 
967 // Calculate the y coordinate based on the x coordinate.
968 // Currently, only the y^2 = x^3 + a*x + b curve equation can be solved.
GetYData(const ECC_Para * para,ECC_Point * pt,bool pcBit)969 static int32_t GetYData(const ECC_Para *para, ECC_Point *pt, bool pcBit)
970 {
971     uint32_t bits = BN_Bits(para->p);
972     BN_BigNum *t1 = BN_Create(bits);
973     BN_BigNum *t2 = BN_Create(bits);
974     BN_BigNum *dupA = BN_Dup(para->a);
975     BN_BigNum *dupB = BN_Dup(para->b);
976     BN_Optimizer *opt = BN_OptimizerCreate();
977     int32_t ret;
978     if (t1 == NULL || t2 == NULL || opt == NULL || dupA == NULL || dupB == NULL) {
979         ret = CRYPT_MEM_ALLOC_FAIL;
980         BSL_ERR_PUSH_ERROR(ret);
981         goto ERR;
982     }
983     if (para->method->bnMontDec != NULL) {
984         para->method->bnMontDec(dupA, para->montP);
985         para->method->bnMontDec(dupB, para->montP);
986     }
987     BN_OptimizerSetLibCtx(para->libCtx, opt);
988     GOTO_ERR_IF(BN_ModSqr(t1, pt->x, para->p, opt), ret);
989     GOTO_ERR_IF(BN_ModMul(t1, t1, pt->x, para->p, opt), ret);
990     GOTO_ERR_IF(BN_ModMul(t2, dupA, pt->x, para->p, opt), ret);
991     GOTO_ERR_IF(BN_ModAdd(t1, t1, t2, para->p, opt), ret);
992     GOTO_ERR_IF(BN_ModAdd(t1, t1, dupB, para->p, opt), ret);
993     GOTO_ERR_IF(BN_ModSqrt(pt->y, t1, para->p, opt), ret);
994 
995     if (BN_GetBit(pt->y, 0) != pcBit) { // if parity is inconsistent, y = -y
996         GOTO_ERR_IF(BN_ModSub(pt->y, para->p, pt->y, para->p, opt), ret);
997     }
998 ERR:
999     BN_Destroy(t1);
1000     BN_Destroy(t2);
1001     BN_Destroy(dupA);
1002     BN_Destroy(dupB);
1003     BN_OptimizerDestroy(opt);
1004     return ret;
1005 }
1006 
1007 // Check whether the parsed data is valid during point decoding and provide compression information.
GetFormatAndCheckLen(const uint8_t * data,uint32_t dataLen,CRYPT_PKEY_PointFormat * format,uint32_t curveBytes)1008 static int32_t GetFormatAndCheckLen(const uint8_t *data, uint32_t dataLen, CRYPT_PKEY_PointFormat *format,
1009     uint32_t curveBytes)
1010 {
1011     if (dataLen < curveBytes + 1) {
1012         BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_POINT_CODE);
1013         return CRYPT_ECC_ERR_POINT_CODE;
1014     }
1015     uint8_t pc = data[0];
1016     /**
1017      * ANS X9.62–2005 A.5.5
1018      * If the compressed form is used PC is either 02 or 03.
1019      * If the uncompressed form is used Verify that PC is 04.
1020      * If the hybrid form is used Verify that PC is either 06 or 07
1021     */
1022     if (pc == 0x04) {
1023         // uncompressed
1024         if (dataLen != (curveBytes << 1) + 1) {
1025             BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_POINT_CODE);
1026             return CRYPT_ECC_ERR_POINT_CODE;
1027         }
1028         *format = CRYPT_POINT_UNCOMPRESSED;
1029         return CRYPT_SUCCESS;
1030     } else if (pc == 0x02 || pc == 0x03) {
1031         // compressed
1032         if (dataLen != curveBytes + 1) {
1033             BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_POINT_CODE);
1034             return CRYPT_ECC_ERR_POINT_CODE;
1035         }
1036         *format = CRYPT_POINT_COMPRESSED;
1037         return CRYPT_SUCCESS;
1038     } else if (pc == 0x06 || pc == 0x07) {
1039         // hybriid
1040         if (dataLen != (curveBytes << 1) + 1) {
1041             BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_POINT_CODE);
1042             return CRYPT_ECC_ERR_POINT_CODE;
1043         }
1044         *format = CRYPT_POINT_HYBRID;
1045         return CRYPT_SUCCESS;
1046     }
1047     BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_POINT_CODE);
1048     return CRYPT_ECC_ERR_POINT_CODE;
1049 }
1050 
ECP_DecodePoint(const ECC_Para * para,ECC_Point * pt,const uint8_t * data,uint32_t dataLen)1051 int32_t ECP_DecodePoint(const ECC_Para *para, ECC_Point *pt, const uint8_t *data, uint32_t dataLen)
1052 {
1053     if (para == NULL || pt == NULL || data == NULL) {
1054         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
1055         return CRYPT_NULL_INPUT;
1056     }
1057     if (para->id != pt->id) {
1058         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
1059         return CRYPT_ECC_POINT_ERR_CURVE_ID;
1060     }
1061     int32_t ret;
1062     uint32_t curveBytes = BN_Bytes(para->p);
1063     CRYPT_PKEY_PointFormat format = CRYPT_POINT_UNCOMPRESSED;
1064     bool pcBit = ((data[0] & 0x01) == 1); // Parity check. If it's odd, return true. If it's even, return false.
1065     GOTO_ERR_IF(GetFormatAndCheckLen(data, dataLen, &format, curveBytes), ret);
1066 
1067     GOTO_ERR_IF(BN_SetLimb(pt->z, 1), ret);
1068     if (format == CRYPT_POINT_COMPRESSED) {
1069         GOTO_ERR_IF(BN_Bin2Bn(pt->x, &data[1], curveBytes), ret);
1070         // The y-coordinate information is obtained through calculation.
1071         GOTO_ERR_IF(GetYData(para, pt, pcBit), ret);
1072     } else if (format == CRYPT_POINT_UNCOMPRESSED) {
1073         GOTO_ERR_IF(BN_Bin2Bn(pt->x, &data[1], curveBytes), ret);
1074         GOTO_ERR_IF(BN_Bin2Bn(pt->y, &data[1 + curveBytes], curveBytes), ret);
1075     } else if (format == CRYPT_POINT_HYBRID) {
1076         GOTO_ERR_IF(BN_Bin2Bn(pt->x, &data[1], curveBytes), ret);
1077         GOTO_ERR_IF(BN_Bin2Bn(pt->y, &data[1 + curveBytes], curveBytes), ret);
1078         // The parity information on the coded information is inconsistent.
1079         if (BN_GetBit(pt->y, 0) != pcBit) {
1080             BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_POINT_CODE);
1081             ret = CRYPT_ECC_ERR_POINT_CODE;
1082             goto ERR;
1083         }
1084     }
1085     // Check whether the value on the point exceeds the modulus field.
1086     if ((BN_Cmp(para->p, pt->y) <= 0) || (BN_Cmp(para->p, pt->x) <= 0)) {
1087         BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_NOT_ON_CURVE);
1088         ret = CRYPT_ECC_POINT_NOT_ON_CURVE;
1089         goto ERR;
1090     }
1091     if (format != CRYPT_POINT_COMPRESSED) {
1092         // Check whether the point is on the curve.
1093         GOTO_ERR_IF(ECP_PointOnCurve(para, pt), ret);
1094     }
1095     return ret;
1096 ERR:
1097     // Ensure that pt is not NULL. Therefore, pt->z is not NULL. This invoking does not fail.
1098     (void)BN_Zeroize(pt->z);
1099     return ret;
1100 }
1101 #endif /* HITLS_CRYPTO_ECC */
1102