1 /*
2  * Copyright (C) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *    http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "ecc_openssl_common.h"
16 
17 #include "securec.h"
18 
19 #include "log.h"
20 #include "memory.h"
21 #include "openssl_adapter.h"
22 #include "utils.h"
23 
NewEcKeyPair(int32_t curveId,EC_KEY ** returnEcKey)24 HcfResult NewEcKeyPair(int32_t curveId, EC_KEY **returnEcKey)
25 {
26     EC_KEY *ecKey = OpensslEcKeyNewByCurveName(curveId);
27     if (ecKey == NULL) {
28         LOGD("[error] new ec key failed.");
29         return HCF_ERR_CRYPTO_OPERATION;
30     }
31     if (OpensslEcKeyGenerateKey(ecKey) <= 0) {
32         LOGD("[error] generate ec key failed.");
33         OpensslEcKeyFree(ecKey);
34         return HCF_ERR_CRYPTO_OPERATION;
35     }
36     if (OpensslEcKeyCheckKey(ecKey) <= 0) {
37         LOGD("[error] check key fail.");
38         OpensslEcKeyFree(ecKey);
39         return HCF_ERR_CRYPTO_OPERATION;
40     }
41     *returnEcKey = ecKey;
42     return HCF_SUCCESS;
43 }
44 
FreeCurveBigNum(BIGNUM * pStd,BIGNUM * bStd,BIGNUM * xStd,BIGNUM * yStd)45 void FreeCurveBigNum(BIGNUM *pStd, BIGNUM *bStd, BIGNUM *xStd, BIGNUM *yStd)
46 {
47     OpensslBnFree(pStd);
48     OpensslBnFree(bStd);
49     OpensslBnFree(xStd);
50     OpensslBnFree(yStd);
51 }
52 
NewGroupFromCurveGFp(const HcfEccCommParamsSpec * ecParams,EC_GROUP ** ecGroup,BN_CTX * ctx)53 static HcfResult NewGroupFromCurveGFp(const HcfEccCommParamsSpec *ecParams, EC_GROUP **ecGroup, BN_CTX *ctx)
54 {
55     HcfResult ret = HCF_SUCCESS;
56     HcfECFieldFp *field = (HcfECFieldFp *)(ecParams->field);
57     BIGNUM *p = NULL;
58     BIGNUM *a = NULL;
59     BIGNUM *b = NULL;
60     EC_GROUP *group = NULL;
61     do {
62         if (BigIntegerToBigNum(&(field->p), &p) != HCF_SUCCESS ||
63             BigIntegerToBigNum(&(ecParams->a), &a) != HCF_SUCCESS ||
64             BigIntegerToBigNum(&(ecParams->b), &b) != HCF_SUCCESS) {
65             LOGD("[error] BigInteger to BigNum failed");
66             ret = HCF_ERR_CRYPTO_OPERATION;
67             break;
68         }
69         group = OpensslEcGroupNewCurveGfp(p, a, b, ctx);
70         if (group == NULL) {
71             LOGD("[error] Alloc group memory failed.");
72             ret = HCF_ERR_CRYPTO_OPERATION;
73             break;
74         }
75     } while (0);
76     OpensslBnFree(p);
77     OpensslBnFree(a);
78     OpensslBnFree(b);
79 
80     if (ret == HCF_SUCCESS) {
81         *ecGroup = group;
82         return ret;
83     }
84     OpensslEcGroupFree(group);
85     return ret;
86 }
87 
SetEcPointToGroup(const HcfEccCommParamsSpec * ecParams,EC_GROUP * group,BN_CTX * ctx)88 static HcfResult SetEcPointToGroup(const HcfEccCommParamsSpec *ecParams, EC_GROUP *group, BN_CTX *ctx)
89 {
90     HcfResult ret = HCF_SUCCESS;
91     BIGNUM *x = NULL;
92     BIGNUM *y = NULL;
93     BIGNUM *order = NULL;
94     EC_POINT *generator = NULL;
95     BIGNUM *cofactor = OpensslBnNew();
96     if (cofactor == NULL) {
97         LOGE("Alloc cofactor memory failed.");
98         return HCF_ERR_MALLOC;
99     }
100     do {
101         if (BigIntegerToBigNum(&(ecParams->g.x), &x) != HCF_SUCCESS ||
102             BigIntegerToBigNum(&(ecParams->g.y), &y) != HCF_SUCCESS ||
103             BigIntegerToBigNum(&(ecParams->n), &order) != HCF_SUCCESS ||
104             !OpensslBnSetWord(cofactor, (uint32_t)ecParams->h)) {
105             LOGD("[error] BigInteger to BigNum failed.");
106             ret = HCF_ERR_CRYPTO_OPERATION;
107             break;
108         }
109         generator = OpensslEcPointNew(group);
110         if (generator == NULL) {
111             LOGE("Alloc group memory failed.");
112             ret = HCF_ERR_CRYPTO_OPERATION;
113             break;
114         }
115         if (!OpensslEcPointSetAffineCoordinatesGfp(group, generator, x, y, ctx)) {
116             LOGD("[error] OpensslEcPointSetAffineCoordinatesGfp failed.");
117             ret = HCF_ERR_CRYPTO_OPERATION;
118             HcfPrintOpensslError();
119             break;
120         }
121 
122         if (!OpensslEcGroupSetGenerator(group, generator, order, cofactor)) {
123             LOGD("[error] OpensslEcGroupSetGenerator failed.");
124             ret = HCF_ERR_CRYPTO_OPERATION;
125             HcfPrintOpensslError();
126             break;
127         }
128     } while (0);
129     OpensslBnFree(x);
130     OpensslBnFree(y);
131     OpensslBnFree(order);
132     OpensslBnFree(cofactor);
133     OpensslEcPointFree(generator);
134     return ret;
135 }
136 
GenerateEcGroupWithParamsSpec(const HcfEccCommParamsSpec * ecParams,EC_GROUP ** ecGroup)137 HcfResult GenerateEcGroupWithParamsSpec(const HcfEccCommParamsSpec *ecParams, EC_GROUP **ecGroup)
138 {
139     if (ecParams == NULL || ecGroup == NULL) {
140         LOGE("Invalid input parameters.");
141         return HCF_INVALID_PARAMS;
142     }
143     EC_GROUP *group = NULL;
144     BN_CTX *ctx = OpensslBnCtxNew();
145     if (ctx == NULL) {
146         LOGE("Alloc ctx memory failed.");
147         return HCF_ERR_MALLOC;
148     }
149     HcfResult ret = NewGroupFromCurveGFp(ecParams, &group, ctx);
150     if (ret != HCF_SUCCESS) {
151         LOGD("[error] New Ec group fail");
152         OpensslBnCtxFree(ctx);
153         return ret;
154     }
155     ret = SetEcPointToGroup(ecParams, group, ctx);
156     if (ret != HCF_SUCCESS) {
157         OpensslBnCtxFree(ctx);
158         OpensslEcGroupFree(group);
159         LOGD("[error] Set Ec point fail");
160         return ret;
161     }
162     OpensslBnCtxFree(ctx);
163     *ecGroup = group;
164     return ret;
165 }
166 
InitEcKeyByPubKey(const HcfPoint * pubKey,EC_KEY * ecKey)167 static HcfResult InitEcKeyByPubKey(const HcfPoint *pubKey, EC_KEY *ecKey)
168 {
169     const EC_GROUP *group = OpensslEcKeyGet0Group(ecKey);
170     if (group == NULL) {
171         LOGD("[error] Not find group from ecKey.");
172         return HCF_ERR_CRYPTO_OPERATION;
173     }
174     EC_POINT *point = OpensslEcPointNew(group);
175     if (point == NULL) {
176         LOGD("[error] New ec point failed.");
177         return HCF_ERR_CRYPTO_OPERATION;
178     }
179     BIGNUM *pkX = NULL;
180     BIGNUM *pkY = NULL;
181     if (BigIntegerToBigNum(&(pubKey->x), &pkX) != HCF_SUCCESS ||
182         BigIntegerToBigNum(&(pubKey->y), &pkY) != HCF_SUCCESS) {
183         LOGD("[error] BigInteger to BigNum failed.");
184         OpensslEcPointFree(point);
185         OpensslBnFree(pkX);
186         OpensslBnFree(pkY);
187         return HCF_ERR_CRYPTO_OPERATION;
188     }
189 
190     // only support fp point.
191     // can use EC_POINT_set_affine_coordinates() set x and y by group, deep copy.
192     int32_t ret = (int32_t)OpensslEcPointSetAffineCoordinatesGfp(group, point, pkX, pkY, NULL);
193     OpensslBnFree(pkX);
194     OpensslBnFree(pkY);
195 
196     if (ret != HCF_OPENSSL_SUCCESS) {
197         LOGD("[error] OpensslEcPointSetAffineCoordinatesGfp failed.");
198         OpensslEcPointFree(point);
199         return HCF_ERR_CRYPTO_OPERATION;
200     }
201     ret = OpensslEcKeySetPublicKey(ecKey, point);
202     if (ret != HCF_OPENSSL_SUCCESS) {
203         LOGD("[error] OpensslEcKeySetPublicKey failed.");
204         OpensslEcPointFree(point);
205         return HCF_ERR_CRYPTO_OPERATION;
206     }
207     OpensslEcPointFree(point);
208     return HCF_SUCCESS;
209 }
210 
InitEcKeyByPriKey(const HcfBigInteger * priKey,EC_KEY * ecKey)211 static HcfResult InitEcKeyByPriKey(const HcfBigInteger *priKey, EC_KEY *ecKey)
212 {
213     BIGNUM *sk = NULL;
214     if (BigIntegerToBigNum(priKey, &sk) != HCF_SUCCESS) {
215         LOGD("[error] BigInteger to BigNum failed.");
216         return HCF_ERR_CRYPTO_OPERATION;
217     }
218     int32_t ret = (int32_t)OpensslEcKeySetPrivateKey(ecKey, sk);
219     if (ret != HCF_OPENSSL_SUCCESS) {
220         LOGD("[error] OpensslEcKeySetPrivateKey failed.");
221         OpensslBnClearFree(sk);
222         return HCF_ERR_CRYPTO_OPERATION;
223     }
224     OpensslBnClearFree(sk);
225     return HCF_SUCCESS;
226 }
227 
SetEcPubKeyFromPriKey(const HcfBigInteger * priKey,EC_KEY * ecKey)228 static HcfResult SetEcPubKeyFromPriKey(const HcfBigInteger *priKey, EC_KEY *ecKey)
229 {
230     const EC_GROUP *group = OpensslEcKeyGet0Group(ecKey);
231     if (group == NULL) {
232         LOGD("[error] Not find group from ecKey.");
233         return HCF_ERR_CRYPTO_OPERATION;
234     }
235     BIGNUM *sk = NULL;
236     if (BigIntegerToBigNum(priKey, &sk) != HCF_SUCCESS) {
237         LOGD("[error] BigInteger to BigNum failed.");
238         return HCF_ERR_CRYPTO_OPERATION;
239     }
240     HcfResult ret = HCF_SUCCESS;
241     EC_POINT *point = OpensslEcPointNew(group);
242     do {
243         if (point == NULL) {
244             LOGD("[error] OpensslEcPointNew failed.");
245             ret = HCF_ERR_CRYPTO_OPERATION;
246             break;
247         }
248         if (!OpensslEcPointMul(group, point, sk, NULL, NULL, NULL)) {
249             LOGD("[error] EC_POINT_mul failed.");
250             ret = HCF_ERR_CRYPTO_OPERATION;
251             break;
252         }
253         if (!OpensslEcKeySetPublicKey(ecKey, point)) {
254             LOGD("[error] OpensslEcKeySetPublicKey failed.");
255             ret = HCF_ERR_CRYPTO_OPERATION;
256         }
257     } while (0);
258     OpensslEcPointFree(point);
259     OpensslBnClearFree(sk);
260     return ret;
261 }
262 
SetEcKey(const HcfPoint * pubKey,const HcfBigInteger * priKey,EC_KEY * ecKey)263 HcfResult SetEcKey(const HcfPoint *pubKey, const HcfBigInteger *priKey, EC_KEY *ecKey)
264 {
265     HcfResult ret = HCF_SUCCESS;
266     if (pubKey != NULL) {
267         ret = InitEcKeyByPubKey(pubKey, ecKey);
268         if (ret != HCF_SUCCESS) {
269             LOGD("[error] InitEcKeyByPubKey failed.");
270             return HCF_ERR_CRYPTO_OPERATION;
271         }
272     }
273     if (priKey != NULL) {
274         ret = InitEcKeyByPriKey(priKey, ecKey);
275         if (ret != HCF_SUCCESS) {
276             LOGD("[error] InitEcKeyByPriKey failed.");
277             return HCF_ERR_CRYPTO_OPERATION;
278         }
279         if (pubKey == NULL) {
280             ret = SetEcPubKeyFromPriKey(priKey, ecKey);
281             if (ret != HCF_SUCCESS) {
282                 LOGD("[error] SetEcPubKeyFromPriKey failed.");
283                 return HCF_ERR_CRYPTO_OPERATION;
284             }
285         }
286     }
287     return ret;
288 }
289 
GetCurveGFp(const EC_GROUP * group,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)290 HcfResult GetCurveGFp(const EC_GROUP *group, const AsyKeySpecItem item, HcfBigInteger *returnBigInteger)
291 {
292     BIGNUM *p = OpensslBnNew();
293     BIGNUM *a = OpensslBnNew();
294     BIGNUM *b = OpensslBnNew();
295     if (p == NULL || a == NULL || b == NULL) {
296         LOGD("[error] new BN failed.");
297         OpensslBnFree(p);
298         OpensslBnFree(a);
299         OpensslBnFree(b);
300         return HCF_ERR_CRYPTO_OPERATION;
301     }
302 
303     if (OpensslEcGroupGetCurveGfp(group, p, a, b, NULL) != HCF_OPENSSL_SUCCESS) {
304         LOGD("[error] OpensslEcGroupGetCurveGfp failed.");
305         OpensslBnFree(p);
306         OpensslBnFree(a);
307         OpensslBnFree(b);
308         return HCF_ERR_CRYPTO_OPERATION;
309     }
310 
311     HcfResult ret = HCF_INVALID_PARAMS;
312     int curveId = OpensslEcGroupGetCurveName(group);
313     if (curveId == NID_secp256k1 && item == ECC_A_BN) {
314         ret = BigNumToBigIntegerSecp256k1(a, returnBigInteger);
315         OpensslBnFree(p);
316         OpensslBnFree(a);
317         OpensslBnFree(b);
318         return ret;
319     }
320     switch (item) {
321         case ECC_FP_P_BN:
322             ret = BigNumToBigInteger(p, returnBigInteger);
323             break;
324         case ECC_A_BN:
325             ret = BigNumToBigInteger(a, returnBigInteger);
326             break;
327         case ECC_B_BN:
328             ret = BigNumToBigInteger(b, returnBigInteger);
329             break;
330         default:
331             LOGD("[error] Invalid ecc key big number spec!");
332             break;
333     }
334     OpensslBnFree(p);
335     OpensslBnFree(a);
336     OpensslBnFree(b);
337     return ret;
338 }
339 
GetGenerator(const EC_GROUP * group,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)340 HcfResult GetGenerator(const EC_GROUP *group, const AsyKeySpecItem item, HcfBigInteger *returnBigInteger)
341 {
342     const EC_POINT *generator = OpensslEcGroupGet0Generator(group);
343     if (generator == NULL) {
344         LOGD("[error] OpensslEcGroupGet0Generator failed.");
345         return HCF_ERR_CRYPTO_OPERATION;
346     }
347 
348     BIGNUM *gX = OpensslBnNew();
349     BIGNUM *gY = OpensslBnNew();
350     if (gX == NULL || gY == NULL) {
351         LOGD("[error] new BN failed.");
352         OpensslBnFree(gX);
353         OpensslBnFree(gY);
354         return HCF_ERR_CRYPTO_OPERATION;
355     }
356 
357     if (OpensslEcPointGetAffineCoordinatesGfp(group, generator, gX, gY, NULL) != HCF_OPENSSL_SUCCESS) {
358         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
359         OpensslBnFree(gX);
360         OpensslBnFree(gY);
361         return HCF_ERR_CRYPTO_OPERATION;
362     }
363 
364     HcfResult ret = HCF_INVALID_PARAMS;
365     switch (item) {
366         case ECC_G_X_BN:
367             ret = BigNumToBigInteger(gX, returnBigInteger);
368             break;
369         case ECC_G_Y_BN:
370             ret = BigNumToBigInteger(gY, returnBigInteger);
371             break;
372         default:
373             LOGE("Invalid ecc key big number spec!");
374             break;
375     }
376     OpensslBnFree(gX);
377     OpensslBnFree(gY);
378     return ret;
379 }
380 
GetOrder(const EC_GROUP * group,HcfBigInteger * returnBigInteger)381 HcfResult GetOrder(const EC_GROUP *group, HcfBigInteger *returnBigInteger)
382 {
383     BIGNUM *order = OpensslBnNew();
384     if (order == NULL) {
385         LOGD("[error] new BN failed.");
386         return HCF_ERR_CRYPTO_OPERATION;
387     }
388 
389     if (OpensslEcGroupGetOrder(group, order, NULL) != HCF_OPENSSL_SUCCESS) {
390         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
391         OpensslBnFree(order);
392         return HCF_ERR_CRYPTO_OPERATION;
393     }
394 
395     HcfResult ret = BigNumToBigInteger(order, returnBigInteger);
396     OpensslBnFree(order);
397     return ret;
398 }
399 
GetCofactor(const EC_GROUP * group,int * returnCofactor)400 HcfResult GetCofactor(const EC_GROUP *group, int *returnCofactor)
401 {
402     BIGNUM *cofactor = OpensslBnNew();
403     if (cofactor == NULL) {
404         LOGD("[error] new BN failed.");
405         return HCF_ERR_CRYPTO_OPERATION;
406     }
407 
408     if (OpensslEcGroupGetCofactor(group, cofactor, NULL) != HCF_OPENSSL_SUCCESS) {
409         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
410         OpensslBnFree(cofactor);
411         return HCF_ERR_CRYPTO_OPERATION;
412     }
413 
414     *returnCofactor = (int)(OpensslBnGetWord(cofactor));
415     // cofactor should not be zero.
416     if (*returnCofactor == 0) {
417         LOGD("[error] OpensslBnGetWord failed.");
418         OpensslBnFree(cofactor);
419         return HCF_ERR_CRYPTO_OPERATION;
420     }
421     OpensslBnFree(cofactor);
422     return HCF_SUCCESS;
423 }
424 
GetFieldSize(const EC_GROUP * group,int32_t * fieldSize)425 HcfResult GetFieldSize(const EC_GROUP *group, int32_t *fieldSize)
426 {
427     *fieldSize = OpensslEcGroupGetDegree(group);
428     if (*fieldSize == 0) {
429         LOGD("[error] OpensslEcGroupGetDegree failed.");
430         return HCF_ERR_CRYPTO_OPERATION;
431     }
432     return HCF_SUCCESS;
433 }
434 
GetFieldType(const HcfKey * self,const bool isPrivate,char ** returnString)435 HcfResult GetFieldType(const HcfKey *self, const bool isPrivate, char **returnString)
436 {
437     char *fieldType = NULL;
438     if (isPrivate) {
439         fieldType = ((HcfOpensslEccPriKey *)self)->fieldType;
440     } else {
441         fieldType = ((HcfOpensslEccPubKey *)self)->fieldType;
442     }
443 
444     if (fieldType == NULL) {
445         LOGE("No fieldType in EccPubKey struct.");
446         return HCF_INVALID_PARAMS;
447     }
448 
449     size_t len = HcfStrlen(fieldType);
450     if (len == 0) {
451         LOGE("fieldType is empty!");
452         return HCF_INVALID_PARAMS;
453     }
454     *returnString = (char *)HcfMalloc(len + 1, 0);
455     if (*returnString == NULL) {
456         LOGE("Alloc returnString memory failed.");
457         return HCF_ERR_MALLOC;
458     }
459     (void)memcpy_s(*returnString, len, fieldType, len);
460 
461     return HCF_SUCCESS;
462 }
463 
GetPubKeyXOrY(const EC_GROUP * group,const EC_POINT * point,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)464 static HcfResult GetPubKeyXOrY(const EC_GROUP *group, const EC_POINT *point, const AsyKeySpecItem item,
465     HcfBigInteger *returnBigInteger)
466 {
467     BIGNUM *pkX = OpensslBnNew();
468     BIGNUM *pkY = OpensslBnNew();
469     if (pkX == NULL || pkY == NULL) {
470         LOGD("[error] new BN failed.");
471         OpensslBnFree(pkX);
472         OpensslBnFree(pkY);
473         return HCF_ERR_CRYPTO_OPERATION;
474     }
475 
476     if (OpensslEcPointGetAffineCoordinatesGfp(group, point, pkX, pkY, NULL) != HCF_OPENSSL_SUCCESS) {
477         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
478         OpensslBnFree(pkX);
479         OpensslBnFree(pkY);
480         return HCF_ERR_CRYPTO_OPERATION;
481     }
482 
483     HcfResult ret = HCF_INVALID_PARAMS;
484     switch (item) {
485         case ECC_PK_X_BN:
486             ret = BigNumToBigInteger(pkX, returnBigInteger);
487             break;
488         case ECC_PK_Y_BN:
489             ret = BigNumToBigInteger(pkY, returnBigInteger);
490             break;
491         default:
492             LOGD("[error] Invalid ecc key big number spec!");
493             break;
494     }
495     OpensslBnFree(pkX);
496     OpensslBnFree(pkY);
497     return ret;
498 }
499 
GetPkSkBigInteger(const HcfKey * self,bool isPrivate,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)500 HcfResult GetPkSkBigInteger(const HcfKey *self, bool isPrivate,
501     const AsyKeySpecItem item, HcfBigInteger *returnBigInteger)
502 {
503     HcfResult ret = HCF_INVALID_PARAMS;
504     if (item == ECC_SK_BN) {
505         if (!isPrivate) {
506             LOGD("[error] ecc pub key has no private key spec item");
507             return ret;
508         }
509         ret = BigNumToBigInteger(OpensslEcKeyGet0PrivateKey(((HcfOpensslEccPriKey *)self)->ecKey),
510             returnBigInteger);
511     } else {
512         if (isPrivate) {
513             LOGD("[error] ecc pri key cannot get pub key spec item");
514             return ret;
515         }
516         ret = GetPubKeyXOrY(OpensslEcKeyGet0Group(((HcfOpensslEccPubKey *)self)->ecKey),
517             OpensslEcKeyGet0PublicKey(((HcfOpensslEccPubKey *)self)->ecKey), item, returnBigInteger);
518     }
519     return ret;
520 }
521