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
ECC_NewPoint(const ECC_Para * para)26 ECC_Point *ECC_NewPoint(const ECC_Para *para)
27 {
28 if (para == NULL) {
29 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
30 return NULL;
31 }
32 uint32_t bits = BN_Bits(para->p);
33 ECC_Point *pt = BSL_SAL_Malloc(sizeof(ECC_Point));
34 if (pt == NULL) {
35 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
36 return NULL;
37 }
38 pt->id = para->id;
39 pt->x = BN_Create(bits);
40 pt->y = BN_Create(bits);
41 pt->z = BN_Create(bits);
42 if (pt->x == NULL || pt->y == NULL || pt->z == NULL) {
43 ECC_FreePoint(pt);
44 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
45 return NULL;
46 }
47 return pt;
48 }
49
ECC_FreePoint(ECC_Point * pt)50 void ECC_FreePoint(ECC_Point *pt)
51 {
52 if (pt == NULL) {
53 return;
54 }
55 BN_Destroy(pt->x);
56 BN_Destroy(pt->y);
57 BN_Destroy(pt->z);
58 BSL_SAL_Free(pt);
59 }
60
ECC_SetLibCtx(void * libCtx,ECC_Para * para)61 void ECC_SetLibCtx(void *libCtx, ECC_Para *para)
62 {
63 para->libCtx = libCtx;
64 }
65
ECC_CopyPoint(ECC_Point * dst,const ECC_Point * src)66 int32_t ECC_CopyPoint(ECC_Point *dst, const ECC_Point *src)
67 {
68 if (dst == NULL || src == NULL) {
69 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
70 return CRYPT_NULL_INPUT;
71 }
72 if (dst->id != src->id) {
73 BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
74 return CRYPT_ECC_POINT_ERR_CURVE_ID;
75 }
76 int32_t ret;
77 GOTO_ERR_IF(BN_Copy(dst->x, src->x), ret);
78 GOTO_ERR_IF(BN_Copy(dst->y, src->y), ret);
79 GOTO_ERR_IF(BN_Copy(dst->z, src->z), ret);
80 ERR:
81 return ret;
82 }
83
ECC_DupPoint(const ECC_Point * pt)84 ECC_Point *ECC_DupPoint(const ECC_Point *pt)
85 {
86 if (pt == NULL) {
87 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
88 return NULL;
89 }
90 ECC_Point *newPt = BSL_SAL_Malloc(sizeof(ECC_Point));
91 if (newPt == NULL) {
92 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
93 return NULL;
94 }
95 newPt->id = pt->id;
96 newPt->x = BN_Dup(pt->x);
97 newPt->y = BN_Dup(pt->y);
98 newPt->z = BN_Dup(pt->z);
99 if (newPt->x == NULL || newPt->y == NULL || newPt->z == NULL) {
100 ECC_FreePoint(newPt);
101 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
102 return NULL;
103 }
104 return newPt;
105 }
106
107 // Convert to Cartesian coordinates
ECC_GetPoint(const ECC_Para * para,ECC_Point * pt,CRYPT_Data * x,CRYPT_Data * y)108 int32_t ECC_GetPoint(const ECC_Para *para, ECC_Point *pt, CRYPT_Data *x, CRYPT_Data *y)
109 {
110 int32_t ret;
111 uint32_t pBytes;
112 if (para == NULL || pt == NULL || x == NULL || x->data == NULL ||
113 ((y != NULL) && (y->data == NULL))) {
114 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
115 return CRYPT_NULL_INPUT;
116 }
117 if (para->id != pt->id) {
118 BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
119 return CRYPT_ECC_POINT_ERR_CURVE_ID;
120 }
121 pBytes = BN_Bytes(para->p);
122 if ((x->len < pBytes) || ((y != NULL) && (y->len < pBytes))) {
123 BSL_ERR_PUSH_ERROR(CRYPT_ECC_BUFF_LEN_NOT_ENOUGH);
124 return CRYPT_ECC_BUFF_LEN_NOT_ENOUGH;
125 }
126 if (BN_IsZero(pt->z)) { // infinity point
127 BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
128 return CRYPT_ECC_POINT_AT_INFINITY;
129 }
130 if (para->method->point2Affine == NULL) {
131 BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
132 return CRYPT_ECC_NOT_SUPPORT;
133 }
134 GOTO_ERR_IF(para->method->point2Affine(para, pt, pt), ret);
135 GOTO_ERR_IF(BN_Bn2BinFixZero(pt->x, x->data, pBytes), ret);
136 x->len = pBytes;
137 if (y != NULL) {
138 GOTO_ERR_IF(BN_Bn2BinFixZero(pt->y, y->data, pBytes), ret);
139 y->len = pBytes;
140 }
141 ERR:
142 return ret;
143 }
144
ECC_Point2Affine(const ECC_Para * para,ECC_Point * r,const ECC_Point * a)145 int32_t ECC_Point2Affine(const ECC_Para *para, ECC_Point *r, const ECC_Point *a)
146 {
147 if (para == NULL || r == NULL || a == NULL) {
148 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
149 return CRYPT_NULL_INPUT;
150 }
151 if (para->id != a->id || para->id != r->id) {
152 BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_ERR_CURVE_ID);
153 return CRYPT_ECC_POINT_ERR_CURVE_ID;
154 }
155 if (BN_IsZero(a->z)) { // infinity point
156 BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
157 return CRYPT_ECC_POINT_AT_INFINITY;
158 }
159 if (para->method->point2Affine == NULL) {
160 BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
161 return CRYPT_ECC_NOT_SUPPORT;
162 }
163 int32_t ret = para->method->point2Affine(para, r, a);
164 if (ret != CRYPT_SUCCESS) {
165 BSL_ERR_PUSH_ERROR(ret);
166 }
167 return ret;
168 }
169
ECC_GetPoint2Bn(const ECC_Para * para,ECC_Point * pt,BN_BigNum * x,BN_BigNum * y)170 int32_t ECC_GetPoint2Bn(const ECC_Para *para, ECC_Point *pt, BN_BigNum *x, BN_BigNum *y)
171 {
172 int32_t ret;
173 GOTO_ERR_IF(ECC_GetPointDataX(para, pt, x), ret);
174 if (y != NULL) {
175 GOTO_ERR_IF(BN_Copy(y, pt->y), ret);
176 }
177 ERR:
178 return ret;
179 }
180
ECC_GetPointDataX(const ECC_Para * para,ECC_Point * pt,BN_BigNum * x)181 int32_t ECC_GetPointDataX(const ECC_Para *para, ECC_Point *pt, BN_BigNum *x)
182 {
183 int32_t ret;
184 if (x == NULL) {
185 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
186 return CRYPT_NULL_INPUT;
187 }
188 GOTO_ERR_IF(ECP_PointAtInfinity(para, pt), ret);
189 if (para->method->point2Affine == NULL) {
190 BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
191 return CRYPT_ECC_NOT_SUPPORT;
192 }
193 GOTO_ERR_IF(para->method->point2Affine(para, pt, pt), ret);
194 GOTO_ERR_IF(BN_Copy(x, pt->x), ret);
195 ERR:
196 return ret;
197 }
198
ECC_GetGFromPara(const ECC_Para * para)199 ECC_Point *ECC_GetGFromPara(const ECC_Para *para)
200 {
201 if (para == NULL) {
202 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
203 return NULL;
204 }
205 ECC_Point *pt = ECC_NewPoint(para);
206 if (pt == NULL) {
207 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
208 return NULL;
209 }
210 (void)BN_Copy(pt->x, para->x);
211 (void)BN_Copy(pt->y, para->y);
212 (void)BN_SetLimb(pt->z, 1);
213 return pt;
214 }
215
ECC_PointMulAdd(ECC_Para * para,ECC_Point * r,const BN_BigNum * k1,const BN_BigNum * k2,const ECC_Point * pt)216 int32_t ECC_PointMulAdd(ECC_Para *para, ECC_Point *r,
217 const BN_BigNum *k1, const BN_BigNum *k2, const ECC_Point *pt)
218 {
219 if (para == NULL) {
220 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
221 return CRYPT_NULL_INPUT;
222 }
223 if (para->method->pointMulAdd == NULL) {
224 BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
225 return CRYPT_ECC_NOT_SUPPORT;
226 }
227 return para->method->pointMulAdd(para, r, k1, k2, pt);
228 }
229
ECC_PointMul(ECC_Para * para,ECC_Point * r,const BN_BigNum * k,const ECC_Point * pt)230 int32_t ECC_PointMul(ECC_Para *para, ECC_Point *r,
231 const BN_BigNum *k, const ECC_Point *pt)
232 {
233 if (para == NULL) {
234 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
235 return CRYPT_NULL_INPUT;
236 }
237 if (para->method->pointMul == NULL) {
238 BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
239 return CRYPT_ECC_NOT_SUPPORT;
240 }
241 return para->method->pointMul(para, r, k, pt);
242 }
243
ECC_PointCmp(const ECC_Para * para,const ECC_Point * a,const ECC_Point * b)244 int32_t ECC_PointCmp(const ECC_Para *para, const ECC_Point *a, const ECC_Point *b)
245 {
246 // Currently, only prime number curves are supported. Other curves need to be expanded.
247 return ECP_PointCmp(para, a, b);
248 }
249
ECC_DupPara(const ECC_Para * para)250 ECC_Para *ECC_DupPara(const ECC_Para *para)
251 {
252 if (para == NULL) {
253 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
254 return NULL;
255 }
256 return ECC_NewPara(para->id);
257 }
258
ECC_ParaBits(const ECC_Para * para)259 uint32_t ECC_ParaBits(const ECC_Para *para)
260 {
261 if (para == NULL) {
262 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
263 return 0;
264 }
265 return BN_Bits(para->p);
266 }
267
ECC_GetParaH(const ECC_Para * para)268 BN_BigNum *ECC_GetParaH(const ECC_Para *para)
269 {
270 if (para == NULL) {
271 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
272 return NULL;
273 }
274 return BN_Dup(para->h);
275 }
276
ECC_GetParaN(const ECC_Para * para)277 BN_BigNum *ECC_GetParaN(const ECC_Para *para)
278 {
279 if (para == NULL) {
280 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
281 return NULL;
282 }
283 return BN_Dup(para->n);
284 }
285
ECC_GetParaA(const ECC_Para * para)286 BN_BigNum *ECC_GetParaA(const ECC_Para *para)
287 {
288 if (para == NULL) {
289 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
290 return NULL;
291 }
292 BN_BigNum *dupA = BN_Dup(para->a);
293 if (dupA == NULL) {
294 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
295 goto ERR;
296 }
297 if (para->method->bnMontDec != NULL) {
298 para->method->bnMontDec(dupA, para->montP);
299 }
300 return dupA;
301 ERR:
302 BN_Destroy(dupA);
303 return NULL;
304 }
305
ECC_GetParaB(const ECC_Para * para)306 BN_BigNum *ECC_GetParaB(const ECC_Para *para)
307 {
308 if (para == NULL) {
309 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
310 return NULL;
311 }
312 BN_BigNum *dupB = BN_Dup(para->b);
313 if (dupB == NULL) {
314 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
315 goto ERR;
316 }
317 if (para->method->bnMontDec != NULL) {
318 para->method->bnMontDec(dupB, para->montP);
319 }
320 return dupB;
321 ERR:
322 BN_Destroy(dupB);
323 return NULL;
324 }
325
ECC_GetParaX(const ECC_Para * para)326 BN_BigNum *ECC_GetParaX(const ECC_Para *para)
327 {
328 if (para == NULL) {
329 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
330 return NULL;
331 }
332 return BN_Dup(para->x);
333 }
334
ECC_GetParaY(const ECC_Para * para)335 BN_BigNum *ECC_GetParaY(const ECC_Para *para)
336 {
337 if (para == NULL) {
338 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
339 return NULL;
340 }
341 return BN_Dup(para->y);
342 }
343
ECC_EncodePoint(const ECC_Para * para,ECC_Point * pt,uint8_t * data,uint32_t * dataLen,CRYPT_PKEY_PointFormat format)344 int32_t ECC_EncodePoint(const ECC_Para *para, ECC_Point *pt, uint8_t *data, uint32_t *dataLen,
345 CRYPT_PKEY_PointFormat format)
346 {
347 // Currently, only prime number curves are supported. Other curves need to be expanded.
348 return ECP_EncodePoint(para, pt, data, dataLen, format);
349 }
350
ECC_DecodePoint(const ECC_Para * para,ECC_Point * pt,const uint8_t * data,uint32_t dataLen)351 int32_t ECC_DecodePoint(const ECC_Para *para, ECC_Point *pt, const uint8_t *data, uint32_t dataLen)
352 {
353 // Currently, only prime number curves are supported. Other curves need to be expanded.
354 return ECP_DecodePoint(para, pt, data, dataLen);
355 }
356
ECC_PointCheck(const ECC_Point * pt)357 int32_t ECC_PointCheck(const ECC_Point *pt)
358 {
359 if (pt == NULL) {
360 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
361 return CRYPT_NULL_INPUT;
362 }
363 if (BN_IsZero(pt->z)) {
364 BSL_ERR_PUSH_ERROR(CRYPT_ECC_POINT_AT_INFINITY);
365 return CRYPT_ECC_POINT_AT_INFINITY;
366 }
367 return CRYPT_SUCCESS;
368 }
369
ECC_ModOrderInv(const ECC_Para * para,BN_BigNum * r,const BN_BigNum * a)370 int32_t ECC_ModOrderInv(const ECC_Para *para, BN_BigNum *r, const BN_BigNum *a)
371 {
372 if (para == NULL) {
373 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
374 return CRYPT_NULL_INPUT;
375 }
376 if (para->method->modOrdInv == NULL) {
377 BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
378 return CRYPT_ECC_NOT_SUPPORT;
379 }
380 return para->method->modOrdInv(para, r, a);
381 }
382
ECC_PointToMont(const ECC_Para * para,ECC_Point * pt,BN_Optimizer * opt)383 int32_t ECC_PointToMont(const ECC_Para *para, ECC_Point *pt, BN_Optimizer *opt)
384 {
385 if (para == NULL || pt == NULL || opt == NULL) {
386 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
387 return CRYPT_NULL_INPUT;
388 }
389 if (para->method->bnMontEnc == NULL) {
390 return CRYPT_SUCCESS;
391 }
392 int32_t ret;
393 GOTO_ERR_IF(para->method->bnMontEnc(pt->x, para->montP, opt, false), ret);
394 GOTO_ERR_IF(para->method->bnMontEnc(pt->y, para->montP, opt, false), ret);
395 GOTO_ERR_IF(para->method->bnMontEnc(pt->z, para->montP, opt, false), ret);
396 ERR:
397 return ret;
398 }
399
ECC_PointFromMont(const ECC_Para * para,ECC_Point * r)400 void ECC_PointFromMont(const ECC_Para *para, ECC_Point *r)
401 {
402 if (para == NULL || r == NULL || para->method->bnMontDec == NULL) {
403 return;
404 }
405 para->method->bnMontDec(r->x, para->montP);
406 para->method->bnMontDec(r->y, para->montP);
407 para->method->bnMontDec(r->z, para->montP);
408 }
409
410 /*
411 Prime curve, point addition r = a + b
412 Calculation formula:
413 X3 = (Y2*Z1^3-Y1)^2 - (X2*Z1^2-X1)^2 * (X1+X2*Z1^2)
414 Y3 = (Y2*Z1^3-Y1) * (X1*(X2*Z1^2-X1)^2-X3) - Y1 * (X2*Z1^2-X1)^3
415 Z3 = (X2*Z1^2-X1) * Z1
416 */
ECC_PointAddAffine(const ECC_Para * para,ECC_Point * r,const ECC_Point * a,const ECC_Point * b)417 int32_t ECC_PointAddAffine(const ECC_Para *para, ECC_Point *r, const ECC_Point *a, const ECC_Point *b)
418 {
419 int32_t ret;
420 if (para == NULL) {
421 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
422 return CRYPT_NULL_INPUT;
423 }
424 if (para->method->pointAddAffine == NULL) {
425 BSL_ERR_PUSH_ERROR(CRYPT_ECC_NOT_SUPPORT);
426 return CRYPT_ECC_NOT_SUPPORT;
427 }
428 BN_Optimizer *opt = BN_OptimizerCreate();
429 ECC_Point *affineb = ECC_NewPoint(para);
430 ECC_Point *dupA = ECC_DupPoint(a);
431 if (affineb == NULL || opt == NULL || dupA == NULL) {
432 ret = CRYPT_MEM_ALLOC_FAIL;
433 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
434 goto ERR;
435 }
436 GOTO_ERR_IF(ECC_Point2Affine(para, affineb, b), ret);
437 GOTO_ERR_IF(ECC_PointToMont(para, dupA, opt), ret);
438 GOTO_ERR_IF(ECC_PointToMont(para, affineb, opt), ret);
439 GOTO_ERR_IF(para->method->pointAddAffine(para, r, dupA, affineb), ret);
440 ECC_PointFromMont(para, r);
441 ERR:
442 BN_OptimizerDestroy(opt);
443 ECC_FreePoint(dupA);
444 ECC_FreePoint(affineb);
445 return ret;
446 }
447
448 typedef struct {
449 uint32_t ecKeyLen;
450 uint32_t secBits;
451 } ComparableStrengths;
452
453 /* See the standard document
454 https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-57pt1r4.pdf
455 Table 2: Comparable strengths */
456 const ComparableStrengths g_strengthsTable[] = {
457 {512, 256},
458 {384, 192},
459 {256, 128},
460 {224, 112},
461 {160, 80}
462 };
463
ECC_GetSecBits(const ECC_Para * para)464 int32_t ECC_GetSecBits(const ECC_Para *para)
465 {
466 if (para == NULL) {
467 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
468 return 0;
469 }
470 uint32_t bits = BN_Bits(para->n);
471 for (size_t i = 0; i < (sizeof(g_strengthsTable) / sizeof(g_strengthsTable[0])); i++) {
472 if (bits >= g_strengthsTable[i].ecKeyLen) {
473 return g_strengthsTable[i].secBits;
474 }
475 }
476 return bits / 2;
477 }
478 #endif /* HITLS_CRYPTO_ECC */
479