• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     switch (item) {
313         case ECC_FP_P_BN:
314             ret = BigNumToBigInteger(p, returnBigInteger);
315             break;
316         case ECC_A_BN:
317             ret = BigNumToBigInteger(a, returnBigInteger);
318             break;
319         case ECC_B_BN:
320             ret = BigNumToBigInteger(b, returnBigInteger);
321             break;
322         default:
323             LOGD("[error] Invalid ecc key big number spec!");
324             break;
325     }
326     OpensslBnFree(p);
327     OpensslBnFree(a);
328     OpensslBnFree(b);
329     return ret;
330 }
331 
GetGenerator(const EC_GROUP * group,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)332 HcfResult GetGenerator(const EC_GROUP *group, const AsyKeySpecItem item, HcfBigInteger *returnBigInteger)
333 {
334     const EC_POINT *generator = OpensslEcGroupGet0Generator(group);
335     if (generator == NULL) {
336         LOGD("[error] OpensslEcGroupGet0Generator failed.");
337         return HCF_ERR_CRYPTO_OPERATION;
338     }
339 
340     BIGNUM *gX = OpensslBnNew();
341     BIGNUM *gY = OpensslBnNew();
342     if (gX == NULL || gY == NULL) {
343         LOGD("[error] new BN failed.");
344         OpensslBnFree(gX);
345         OpensslBnFree(gY);
346         return HCF_ERR_CRYPTO_OPERATION;
347     }
348 
349     if (OpensslEcPointGetAffineCoordinatesGfp(group, generator, gX, gY, NULL) != HCF_OPENSSL_SUCCESS) {
350         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
351         OpensslBnFree(gX);
352         OpensslBnFree(gY);
353         return HCF_ERR_CRYPTO_OPERATION;
354     }
355 
356     HcfResult ret = HCF_INVALID_PARAMS;
357     switch (item) {
358         case ECC_G_X_BN:
359             ret = BigNumToBigInteger(gX, returnBigInteger);
360             break;
361         case ECC_G_Y_BN:
362             ret = BigNumToBigInteger(gY, returnBigInteger);
363             break;
364         default:
365             LOGE("Invalid ecc key big number spec!");
366             break;
367     }
368     OpensslBnFree(gX);
369     OpensslBnFree(gY);
370     return ret;
371 }
372 
GetOrder(const EC_GROUP * group,HcfBigInteger * returnBigInteger)373 HcfResult GetOrder(const EC_GROUP *group, HcfBigInteger *returnBigInteger)
374 {
375     BIGNUM *order = OpensslBnNew();
376     if (order == NULL) {
377         LOGD("[error] new BN failed.");
378         return HCF_ERR_CRYPTO_OPERATION;
379     }
380 
381     if (OpensslEcGroupGetOrder(group, order, NULL) != HCF_OPENSSL_SUCCESS) {
382         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
383         OpensslBnFree(order);
384         return HCF_ERR_CRYPTO_OPERATION;
385     }
386 
387     HcfResult ret = BigNumToBigInteger(order, returnBigInteger);
388     OpensslBnFree(order);
389     return ret;
390 }
391 
GetCofactor(const EC_GROUP * group,int * returnCofactor)392 HcfResult GetCofactor(const EC_GROUP *group, int *returnCofactor)
393 {
394     BIGNUM *cofactor = OpensslBnNew();
395     if (cofactor == NULL) {
396         LOGD("[error] new BN failed.");
397         return HCF_ERR_CRYPTO_OPERATION;
398     }
399 
400     if (OpensslEcGroupGetCofactor(group, cofactor, NULL) != HCF_OPENSSL_SUCCESS) {
401         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
402         OpensslBnFree(cofactor);
403         return HCF_ERR_CRYPTO_OPERATION;
404     }
405 
406     *returnCofactor = (int)(OpensslBnGetWord(cofactor));
407     // cofactor should not be zero.
408     if (*returnCofactor == 0) {
409         LOGD("[error] OpensslBnGetWord failed.");
410         OpensslBnFree(cofactor);
411         return HCF_ERR_CRYPTO_OPERATION;
412     }
413     OpensslBnFree(cofactor);
414     return HCF_SUCCESS;
415 }
416 
GetFieldSize(const EC_GROUP * group,int32_t * fieldSize)417 HcfResult GetFieldSize(const EC_GROUP *group, int32_t *fieldSize)
418 {
419     *fieldSize = OpensslEcGroupGetDegree(group);
420     if (*fieldSize == 0) {
421         LOGD("[error] OpensslEcGroupGetDegree failed.");
422         return HCF_ERR_CRYPTO_OPERATION;
423     }
424     return HCF_SUCCESS;
425 }
426 
GetFieldType(const HcfKey * self,const bool isPrivate,char ** returnString)427 HcfResult GetFieldType(const HcfKey *self, const bool isPrivate, char **returnString)
428 {
429     char *fieldType = NULL;
430     if (isPrivate) {
431         fieldType = ((HcfOpensslEccPriKey *)self)->fieldType;
432     } else {
433         fieldType = ((HcfOpensslEccPubKey *)self)->fieldType;
434     }
435 
436     if (fieldType == NULL) {
437         LOGE("No fieldType in EccPubKey struct.");
438         return HCF_INVALID_PARAMS;
439     }
440 
441     size_t len = HcfStrlen(fieldType);
442     if (len == 0) {
443         LOGE("fieldType is empty!");
444         return HCF_INVALID_PARAMS;
445     }
446     *returnString = (char *)HcfMalloc(len + 1, 0);
447     if (*returnString == NULL) {
448         LOGE("Alloc returnString memory failed.");
449         return HCF_ERR_MALLOC;
450     }
451     (void)memcpy_s(*returnString, len, fieldType, len);
452 
453     return HCF_SUCCESS;
454 }
455 
GetPubKeyXOrY(const EC_GROUP * group,const EC_POINT * point,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)456 static HcfResult GetPubKeyXOrY(const EC_GROUP *group, const EC_POINT *point, const AsyKeySpecItem item,
457     HcfBigInteger *returnBigInteger)
458 {
459     BIGNUM *pkX = OpensslBnNew();
460     BIGNUM *pkY = OpensslBnNew();
461     if (pkX == NULL || pkY == NULL) {
462         LOGD("[error] new BN failed.");
463         OpensslBnFree(pkX);
464         OpensslBnFree(pkY);
465         return HCF_ERR_CRYPTO_OPERATION;
466     }
467 
468     if (OpensslEcPointGetAffineCoordinatesGfp(group, point, pkX, pkY, NULL) != HCF_OPENSSL_SUCCESS) {
469         LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
470         OpensslBnFree(pkX);
471         OpensslBnFree(pkY);
472         return HCF_ERR_CRYPTO_OPERATION;
473     }
474 
475     HcfResult ret = HCF_INVALID_PARAMS;
476     switch (item) {
477         case ECC_PK_X_BN:
478             ret = BigNumToBigInteger(pkX, returnBigInteger);
479             break;
480         case ECC_PK_Y_BN:
481             ret = BigNumToBigInteger(pkY, returnBigInteger);
482             break;
483         default:
484             LOGD("[error] Invalid ecc key big number spec!");
485             break;
486     }
487     OpensslBnFree(pkX);
488     OpensslBnFree(pkY);
489     return ret;
490 }
491 
GetPkSkBigInteger(const HcfKey * self,bool isPrivate,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)492 HcfResult GetPkSkBigInteger(const HcfKey *self, bool isPrivate,
493     const AsyKeySpecItem item, HcfBigInteger *returnBigInteger)
494 {
495     HcfResult ret = HCF_INVALID_PARAMS;
496     if (item == ECC_SK_BN) {
497         if (!isPrivate) {
498             LOGD("[error] ecc pub key has no private key spec item");
499             return ret;
500         }
501         ret = BigNumToBigInteger(OpensslEcKeyGet0PrivateKey(((HcfOpensslEccPriKey *)self)->ecKey),
502             returnBigInteger);
503     } else {
504         if (isPrivate) {
505             LOGD("[error] ecc pri key cannot get pub key spec item");
506             return ret;
507         }
508         ret = GetPubKeyXOrY(OpensslEcKeyGet0Group(((HcfOpensslEccPubKey *)self)->ecKey),
509             OpensslEcKeyGet0PublicKey(((HcfOpensslEccPubKey *)self)->ecKey), item, returnBigInteger);
510     }
511     return ret;
512 }
513