• 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 
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