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