• 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 = Openssl_EC_KEY_new_by_curve_name(curveId);
27     if (ecKey == NULL) {
28         LOGD("[error] new ec key failed.");
29         return HCF_ERR_CRYPTO_OPERATION;
30     }
31     if (Openssl_EC_KEY_generate_key(ecKey) <= 0) {
32         LOGD("[error] generate ec key failed.");
33         Openssl_EC_KEY_free(ecKey);
34         return HCF_ERR_CRYPTO_OPERATION;
35     }
36     if (Openssl_EC_KEY_check_key(ecKey) <= 0) {
37         LOGD("[error] check key fail.");
38         Openssl_EC_KEY_free(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     Openssl_BN_free(pStd);
48     Openssl_BN_free(bStd);
49     Openssl_BN_free(xStd);
50     Openssl_BN_free(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 = Openssl_EC_GROUP_new_curve_GFp(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     Openssl_BN_free(p);
77     Openssl_BN_free(a);
78     Openssl_BN_free(b);
79 
80     if (ret == HCF_SUCCESS) {
81         *ecGroup = group;
82         return ret;
83     }
84     Openssl_EC_GROUP_free(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 = Openssl_BN_new();
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             !Openssl_BN_set_word(cofactor, (uint32_t)ecParams->h)) {
105             LOGD("[error] BigInteger to BigNum failed.");
106             ret = HCF_ERR_CRYPTO_OPERATION;
107             break;
108         }
109         generator = Openssl_EC_POINT_new(group);
110         if (generator == NULL) {
111             LOGE("Alloc group memory failed.");
112             ret = HCF_ERR_CRYPTO_OPERATION;
113             break;
114         }
115         if (!Openssl_EC_POINT_set_affine_coordinates_GFp(group, generator, x, y, ctx)) {
116             LOGD("[error] Openssl_EC_POINT_set_affine_coordinates_GFp failed.");
117             ret = HCF_ERR_CRYPTO_OPERATION;
118             HcfPrintOpensslError();
119             break;
120         }
121 
122         if (!Openssl_EC_GROUP_set_generator(group, generator, order, cofactor)) {
123             LOGD("[error] Openssl_EC_GROUP_set_generator failed.");
124             ret = HCF_ERR_CRYPTO_OPERATION;
125             HcfPrintOpensslError();
126             break;
127         }
128     } while (0);
129     Openssl_BN_free(x);
130     Openssl_BN_free(y);
131     Openssl_BN_free(order);
132     Openssl_BN_free(cofactor);
133     Openssl_EC_POINT_free(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 = Openssl_BN_CTX_new();
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         Openssl_BN_CTX_free(ctx);
153         return ret;
154     }
155     ret = SetEcPointToGroup(ecParams, group, ctx);
156     if (ret != HCF_SUCCESS) {
157         Openssl_BN_CTX_free(ctx);
158         Openssl_EC_GROUP_free(group);
159         LOGD("[error] Set Ec point fail");
160         return ret;
161     }
162     Openssl_BN_CTX_free(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 = Openssl_EC_KEY_get0_group(ecKey);
170     if (group == NULL) {
171         LOGD("[error] Not find group from ecKey.");
172         return HCF_ERR_CRYPTO_OPERATION;
173     }
174     EC_POINT *point = Openssl_EC_POINT_new(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         Openssl_EC_POINT_free(point);
185         Openssl_BN_free(pkX);
186         Openssl_BN_free(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)Openssl_EC_POINT_set_affine_coordinates_GFp(group, point, pkX, pkY, NULL);
193     Openssl_BN_free(pkX);
194     Openssl_BN_free(pkY);
195 
196     if (ret != HCF_OPENSSL_SUCCESS) {
197         LOGD("[error] Openssl_EC_POINT_set_affine_coordinates_GFp failed.");
198         Openssl_EC_POINT_free(point);
199         return HCF_ERR_CRYPTO_OPERATION;
200     }
201     ret = Openssl_EC_KEY_set_public_key(ecKey, point);
202     if (ret != HCF_OPENSSL_SUCCESS) {
203         LOGD("[error] Openssl_EC_KEY_set_public_key failed.");
204         Openssl_EC_POINT_free(point);
205         return HCF_ERR_CRYPTO_OPERATION;
206     }
207     Openssl_EC_POINT_free(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)Openssl_EC_KEY_set_private_key(ecKey, sk);
219     if (ret != HCF_OPENSSL_SUCCESS) {
220         LOGD("[error] Openssl_EC_KEY_set_private_key failed.");
221         Openssl_BN_free(sk);
222         return HCF_ERR_CRYPTO_OPERATION;
223     }
224     Openssl_BN_free(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 = Openssl_EC_KEY_get0_group(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 = Openssl_EC_POINT_new(group);
242     do {
243         if (point == NULL) {
244             LOGD("[error] Openssl_EC_POINT_new failed.");
245             ret = HCF_ERR_CRYPTO_OPERATION;
246             break;
247         }
248         if (!Openssl_EC_POINT_mul(group, point, sk, NULL, NULL, NULL)) {
249             LOGD("[error] EC_POINT_mul failed.");
250             ret = HCF_ERR_CRYPTO_OPERATION;
251             break;
252         }
253         if (!Openssl_EC_KEY_set_public_key(ecKey, point)) {
254             LOGD("[error] Openssl_EC_KEY_set_public_key failed.");
255             ret = HCF_ERR_CRYPTO_OPERATION;
256         }
257     } while (0);
258     Openssl_EC_POINT_free(point);
259     Openssl_BN_free(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 = Openssl_BN_new();
293     BIGNUM *a = Openssl_BN_new();
294     BIGNUM *b = Openssl_BN_new();
295     if (p == NULL || a == NULL || b == NULL) {
296         LOGD("[error] new BN failed.");
297         Openssl_BN_free(p);
298         Openssl_BN_free(a);
299         Openssl_BN_free(b);
300         return HCF_ERR_CRYPTO_OPERATION;
301     }
302 
303     if (Openssl_EC_GROUP_get_curve_GFp(group, p, a, b, NULL) != HCF_OPENSSL_SUCCESS) {
304         LOGD("[error] Openssl_EC_GROUP_get_curve_GFp failed.");
305         Openssl_BN_free(p);
306         Openssl_BN_free(a);
307         Openssl_BN_free(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     Openssl_BN_free(p);
327     Openssl_BN_free(a);
328     Openssl_BN_free(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 = Openssl_EC_GROUP_get0_generator(group);
335     if (generator == NULL) {
336         LOGD("[error] Openssl_EC_GROUP_get0_generator failed.");
337         return HCF_ERR_CRYPTO_OPERATION;
338     }
339 
340     BIGNUM *gX = Openssl_BN_new();
341     BIGNUM *gY = Openssl_BN_new();
342     if (gX == NULL || gY == NULL) {
343         LOGD("[error] new BN failed.");
344         Openssl_BN_free(gX);
345         Openssl_BN_free(gY);
346         return HCF_ERR_CRYPTO_OPERATION;
347     }
348 
349     if (Openssl_EC_POINT_get_affine_coordinates_GFp(group, generator, gX, gY, NULL) != HCF_OPENSSL_SUCCESS) {
350         LOGD("[error] Openssl_EC_POINT_get_affine_coordinates_GFp failed.");
351         Openssl_BN_free(gX);
352         Openssl_BN_free(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     Openssl_BN_free(gX);
369     Openssl_BN_free(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 = Openssl_BN_new();
376     if (order == NULL) {
377         LOGD("[error] new BN failed.");
378         return HCF_ERR_CRYPTO_OPERATION;
379     }
380 
381     if (Openssl_EC_GROUP_get_order(group, order, NULL) != HCF_OPENSSL_SUCCESS) {
382         LOGD("[error] Openssl_EC_POINT_get_affine_coordinates_GFp failed.");
383         Openssl_BN_free(order);
384         return HCF_ERR_CRYPTO_OPERATION;
385     }
386 
387     HcfResult ret = BigNumToBigInteger(order, returnBigInteger);
388     Openssl_BN_free(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 = Openssl_BN_new();
395     if (cofactor == NULL) {
396         LOGD("[error] new BN failed.");
397         return HCF_ERR_CRYPTO_OPERATION;
398     }
399 
400     if (Openssl_EC_GROUP_get_cofactor(group, cofactor, NULL) != HCF_OPENSSL_SUCCESS) {
401         LOGD("[error] Openssl_EC_POINT_get_affine_coordinates_GFp failed.");
402         Openssl_BN_free(cofactor);
403         return HCF_ERR_CRYPTO_OPERATION;
404     }
405 
406     *returnCofactor = (int)(Openssl_BN_get_word(cofactor));
407     // cofactor should not be zero.
408     if (*returnCofactor == 0) {
409         LOGD("[error] Openssl_BN_get_word failed.");
410         Openssl_BN_free(cofactor);
411         return HCF_ERR_CRYPTO_OPERATION;
412     }
413     Openssl_BN_free(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 = Openssl_EC_GROUP_get_degree(group);
420     if (*fieldSize == 0) {
421         LOGD("[error] Openssl_EC_GROUP_get_degree 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 = Openssl_BN_new();
460     BIGNUM *pkY = Openssl_BN_new();
461     if (pkX == NULL || pkY == NULL) {
462         LOGD("[error] new BN failed.");
463         Openssl_BN_free(pkX);
464         Openssl_BN_free(pkY);
465         return HCF_ERR_CRYPTO_OPERATION;
466     }
467 
468     if (Openssl_EC_POINT_get_affine_coordinates_GFp(group, point, pkX, pkY, NULL) != HCF_OPENSSL_SUCCESS) {
469         LOGD("[error] Openssl_EC_POINT_get_affine_coordinates_GFp failed.");
470         Openssl_BN_free(pkX);
471         Openssl_BN_free(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     Openssl_BN_free(pkX);
488     Openssl_BN_free(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(Openssl_EC_KEY_get0_private_key(((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(Openssl_EC_KEY_get0_group(((HcfOpensslEccPubKey *)self)->ecKey),
509             Openssl_EC_KEY_get0_public_key(((HcfOpensslEccPubKey *)self)->ecKey), item, returnBigInteger);
510     }
511     return ret;
512 }
513