1 /*
2  * Copyright (C) 2023-2024 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 
16 #include "ecc_common_param_spec_generator_openssl.h"
17 #include "securec.h"
18 
19 #include "ecc_openssl_common.h"
20 #include "ecc_openssl_common_param_spec.h"
21 #include "log.h"
22 #include "memory.h"
23 #include "openssl_adapter.h"
24 #include "openssl_class.h"
25 #include "openssl_common.h"
26 #include "utils.h"
27 
BuildEcPoint(const EC_GROUP * ecGroup)28 static EC_POINT *BuildEcPoint(const EC_GROUP *ecGroup)
29 {
30     EC_POINT *point = OpensslEcPointNew(ecGroup);
31     if (point == NULL) {
32         LOGE("new ec point failed.");
33         return NULL;
34     }
35     const EC_POINT *tmpPoint = OpensslEcGroupGet0Generator(ecGroup);
36     if (tmpPoint == NULL) {
37         LOGE("Get ec generator failed.");
38         OpensslEcPointFree(point);
39         return NULL;
40     }
41     if (!OpensslEcPointCopy(point, tmpPoint)) {
42         LOGE("Ec point copy failed.");
43         OpensslEcPointFree(point);
44         return NULL;
45     }
46 
47     return point;
48 }
49 
BuildCommonParamPart(const EC_GROUP * ecGroup,HcfEccCommParamsSpecSpi * returnCommonParamSpec)50 static HcfResult BuildCommonParamPart(const EC_GROUP *ecGroup, HcfEccCommParamsSpecSpi *returnCommonParamSpec)
51 {
52     EC_POINT *point = NULL;
53     point = BuildEcPoint(ecGroup);
54     if (point == NULL) {
55         LOGE("Build ec point failed.");
56         return HCF_ERR_MALLOC;
57     }
58     BIGNUM *x = OpensslBnNew();
59     if (x == NULL) {
60         LOGE("New x failed.");
61         OpensslEcPointFree(point);
62         return HCF_ERR_MALLOC;
63     }
64     BIGNUM *y = OpensslBnNew();
65     if (y == NULL) {
66         LOGE("New y failed.");
67         OpensslBnFree(x);
68         OpensslEcPointFree(point);
69         return HCF_ERR_MALLOC;
70     }
71     HcfResult ret = HCF_SUCCESS;
72     do {
73         if (!OpensslEcPointGetAffineCoordinatesGfp(ecGroup, point, x, y, NULL)) {
74             LOGE("EC_POINT_get_affine_coordinates_GFp failed.");
75             ret = HCF_ERR_CRYPTO_OPERATION;
76             break;
77         }
78         if (BigNumToBigInteger(x, &(returnCommonParamSpec->paramsSpec.g.x)) != HCF_SUCCESS) {
79             LOGE("Build commonParamSpec x failed.");
80             ret = HCF_ERR_CRYPTO_OPERATION;
81             break;
82         }
83         if (BigNumToBigInteger(y, &(returnCommonParamSpec->paramsSpec.g.y)) != HCF_SUCCESS) {
84             LOGE("Build commonParamSpec y failed.");
85             ret = HCF_ERR_CRYPTO_OPERATION;
86             break;
87         }
88     } while (0);
89     OpensslBnFree(x);
90     OpensslBnFree(y);
91     OpensslEcPointFree(point);
92     return ret;
93 }
94 
BuildCommonParamGFp(const EC_GROUP * ecGroup,HcfEccCommParamsSpecSpi * returnCommonParamSpec)95 static HcfResult BuildCommonParamGFp(const EC_GROUP *ecGroup, HcfEccCommParamsSpecSpi *returnCommonParamSpec)
96 {
97     BIGNUM *p = OpensslBnNew();
98     BIGNUM *a = OpensslBnNew();
99     BIGNUM *b = OpensslBnNew();
100     if (p == NULL || a == NULL || b == NULL) {
101         LOGD("[error] new BN failed.");
102         OpensslBnFree(p);
103         OpensslBnFree(a);
104         OpensslBnFree(b);
105         return HCF_ERR_CRYPTO_OPERATION;
106     }
107     if (!OpensslEcGroupGetCurveGfp(ecGroup, p, a, b, NULL)) {
108         LOGE("EC_GROUP_get_curve_GFp failed.");
109         OpensslBnFree(p);
110         OpensslBnFree(a);
111         OpensslBnFree(b);
112         return HCF_ERR_CRYPTO_OPERATION;
113     }
114     HcfResult ret = HCF_SUCCESS;
115     do {
116         if (OpensslEcGroupGetCurveName(ecGroup) == NID_secp256k1) {
117             if (BigNumToBigIntegerSecp256k1(a, &(returnCommonParamSpec->paramsSpec.a)) != HCF_SUCCESS) {
118                 LOGE("Build Secp256k1CommonParamSpec a failed.");
119                 ret = HCF_ERR_CRYPTO_OPERATION;
120                 break;
121             }
122         } else {
123             if (BigNumToBigInteger(a, &(returnCommonParamSpec->paramsSpec.a)) != HCF_SUCCESS) {
124                 LOGE("Build commonParamSpec a failed.");
125                 ret = HCF_ERR_CRYPTO_OPERATION;
126                 break;
127             }
128         }
129         if (BigNumToBigInteger(b, &(returnCommonParamSpec->paramsSpec.b)) != HCF_SUCCESS) {
130             LOGE("Build commonParamSpec b failed.");
131             ret = HCF_ERR_CRYPTO_OPERATION;
132             break;
133         }
134         HcfECFieldFp *tmpField = (HcfECFieldFp *)(returnCommonParamSpec->paramsSpec.field);
135         if (BigNumToBigInteger(p, &(tmpField->p)) != HCF_SUCCESS) {
136             LOGE("Build commonParamSpec p failed.");
137             ret = HCF_ERR_CRYPTO_OPERATION;
138             break;
139         }
140     } while (0);
141 
142     OpensslBnFree(p);
143     OpensslBnFree(a);
144     OpensslBnFree(b);
145     return ret;
146 }
147 
BuildCommonParam(const EC_GROUP * ecGroup,HcfEccCommParamsSpecSpi * returnCommonParamSpec)148 static HcfResult BuildCommonParam(const EC_GROUP *ecGroup, HcfEccCommParamsSpecSpi *returnCommonParamSpec)
149 {
150     if (BuildCommonParamPart(ecGroup, returnCommonParamSpec)!= HCF_SUCCESS) {
151         LOGE("BuildCommonParamPartOne failed.");
152         return HCF_ERR_CRYPTO_OPERATION;
153     }
154     if (BuildCommonParamGFp(ecGroup, returnCommonParamSpec)!= HCF_SUCCESS) {
155         LOGE("BuildCommonParamGFp failed.");
156         return HCF_ERR_CRYPTO_OPERATION;
157     }
158     if (GetOrder(ecGroup, &(returnCommonParamSpec->paramsSpec.n)) != HCF_SUCCESS) {
159         LOGE("Failed to get curve order data.");
160         return HCF_ERR_CRYPTO_OPERATION;
161     }
162 
163     if (GetCofactor(ecGroup, &(returnCommonParamSpec->paramsSpec.h)) != HCF_SUCCESS) {
164         LOGE("Failed to get curve cofactor data.");
165         return HCF_ERR_CRYPTO_OPERATION;
166     }
167     return HCF_SUCCESS;
168 }
169 
BuildEccCommonParamObject(void)170 static HcfEccCommParamsSpecSpi *BuildEccCommonParamObject(void)
171 {
172     HcfEccCommParamsSpecSpi *spi = (HcfEccCommParamsSpecSpi*)HcfMalloc(sizeof(HcfEccCommParamsSpecSpi), 0);
173     if (spi == NULL) {
174         LOGE("failed to build ecc commonParam object.");
175         return NULL;
176     }
177     spi->paramsSpec.field = (HcfECField *)HcfMalloc(sizeof(HcfECFieldFp), 0);
178     if (spi->paramsSpec.field == NULL) {
179         LOGE("field malloc failed.");
180         HcfFree(spi);
181         return NULL;
182     }
183     char *fieldType = "Fp";
184     size_t srcFieldTypeLen = HcfStrlen(fieldType);
185     if (srcFieldTypeLen == 0) {
186         LOGE("fieldType is empty!");
187         HcfFree(spi->paramsSpec.field);
188         HcfFree(spi);
189         return NULL;
190     }
191     spi->paramsSpec.field->fieldType = (char *)HcfMalloc(srcFieldTypeLen + 1, 0);
192     if (spi->paramsSpec.field->fieldType == NULL) {
193         LOGE("fieldType malloc failed.");
194         HcfFree(spi->paramsSpec.field);
195         HcfFree(spi);
196         return NULL;
197     }
198 
199     if (memcpy_s(spi->paramsSpec.field->fieldType, srcFieldTypeLen, fieldType, srcFieldTypeLen) != EOK) {
200         LOGE("memcpy fieldType failed.");
201         HcfFree(spi->paramsSpec.field->fieldType);
202         HcfFree(spi->paramsSpec.field);
203         HcfFree(spi);
204         return NULL;
205     }
206     return spi;
207 }
208 
FreeEccCommParamObject(HcfEccCommParamsSpecSpi * spec)209 static void FreeEccCommParamObject(HcfEccCommParamsSpecSpi *spec)
210 {
211     if (spec == NULL) {
212         LOGE("Invalid input parameter.");
213         return;
214     }
215     HcfFree(spec->paramsSpec.base.algName);
216     spec->paramsSpec.base.algName = NULL;
217     if (spec->paramsSpec.field != NULL) {
218         HcfECFieldFp *tmp = (HcfECFieldFp *)spec->paramsSpec.field;
219         HcfFree(tmp->p.data);
220         tmp->p.data = NULL;
221         HcfFree(spec->paramsSpec.field->fieldType);
222         spec->paramsSpec.field->fieldType = NULL;
223         HcfFree(spec->paramsSpec.field);
224         spec->paramsSpec.field = NULL;
225     }
226     HcfFree(spec->paramsSpec.a.data);
227     spec->paramsSpec.a.data = NULL;
228     HcfFree(spec->paramsSpec.b.data);
229     spec->paramsSpec.b.data = NULL;
230     HcfFree(spec->paramsSpec.n.data);
231     spec->paramsSpec.n.data = NULL;
232     HcfFree(spec->paramsSpec.g.x.data);
233     spec->paramsSpec.g.x.data = NULL;
234     HcfFree(spec->paramsSpec.g.y.data);
235     spec->paramsSpec.g.y.data = NULL;
236     HcfFree(spec);
237 }
238 
HcfECCCommonParamSpecCreate(HcfAsyKeyGenParams * params,HcfEccCommParamsSpecSpi ** returnCommonParamSpec)239 HcfResult HcfECCCommonParamSpecCreate(HcfAsyKeyGenParams *params, HcfEccCommParamsSpecSpi **returnCommonParamSpec)
240 {
241     if ((params == NULL) || (returnCommonParamSpec == NULL)) {
242         LOGE("Invalid input parameter.");
243         return HCF_INVALID_PARAMS;
244     }
245     int32_t curveId = 0;
246     if (params->bits != 0) {
247         if (GetOpensslCurveId(params->bits, &curveId) != HCF_SUCCESS) {
248             LOGE("Get curveId parameter failed.");
249             return HCF_INVALID_PARAMS;
250         }
251     }
252     EC_GROUP *ecGroup = OpensslEcGroupNewByCurveName(curveId);
253     if (ecGroup == NULL) {
254         LOGE("Create ecGroup failed.");
255         return HCF_ERR_CRYPTO_OPERATION;
256     }
257     HcfEccCommParamsSpecSpi *object = BuildEccCommonParamObject();
258     if (object == NULL) {
259         LOGE("Build ecc common params object failed.");
260         OpensslEcGroupFree(ecGroup);
261         return HCF_ERR_MALLOC;
262     }
263     object->paramsSpec.base.specType = HCF_COMMON_PARAMS_SPEC;
264     if (GetAlgNameByBits(params->bits, &(object->paramsSpec.base.algName)) != HCF_SUCCESS) {
265         LOGE("Get algName parameter by bits failed.");
266         FreeEccCommParamObject(object);
267         object = NULL;
268         OpensslEcGroupFree(ecGroup);
269         return HCF_INVALID_PARAMS;
270     }
271     if (BuildCommonParam(ecGroup, object)!= HCF_SUCCESS) {
272         LOGE("Get common params failed.");
273         FreeEccCommParamObject(object);
274         object = NULL;
275         OpensslEcGroupFree(ecGroup);
276         return HCF_ERR_CRYPTO_OPERATION;
277     }
278     *returnCommonParamSpec = object;
279     OpensslEcGroupFree(ecGroup);
280     return HCF_SUCCESS;
281 }
282 
InitEccPoint(const int32_t curveNameValue,EC_GROUP ** ecGroup,EC_POINT ** ecPoint,BIGNUM ** x,BIGNUM ** y)283 static HcfResult InitEccPoint(const int32_t curveNameValue, EC_GROUP **ecGroup,
284                               EC_POINT **ecPoint, BIGNUM **x, BIGNUM **y)
285 {
286     int32_t nid = 0;
287     if (GetNidByCurveNameValue(curveNameValue, &nid) != HCF_SUCCESS) {
288         LOGE("Failed to get curveNameValue.");
289         return HCF_INVALID_PARAMS;
290     }
291     *ecGroup = OpensslEcGroupNewByCurveName(nid);
292     if (*ecGroup == NULL) {
293         LOGE("Failed to create EC group with nid %d.", nid);
294         return HCF_ERR_CRYPTO_OPERATION;
295     }
296     *ecPoint = OpensslEcPointNew(*ecGroup);
297     if (*ecPoint == NULL) {
298         LOGE("Failed to allocate memory for EC_POINT.");
299         OpensslEcGroupFree(*ecGroup);
300         *ecGroup = NULL;
301         return HCF_ERR_CRYPTO_OPERATION;
302     }
303     if (x != NULL) {
304         *x = OpensslBnNew();
305         if (*x == NULL) {
306             LOGE("Failed to allocate memory for BIGNUM x.");
307             OpensslEcGroupFree(*ecGroup);
308             *ecGroup = NULL;
309             OpensslEcPointFree(*ecPoint);
310             *ecPoint = NULL;
311             return HCF_ERR_CRYPTO_OPERATION;
312         }
313     }
314     if (y != NULL) {
315         *y = OpensslBnNew();
316         if (*y == NULL) {
317             LOGE("Failed to allocate memory for BIGNUM y.");
318             OpensslBnFree(*x);
319             *x = NULL;
320             OpensslEcGroupFree(*ecGroup);
321             *ecGroup = NULL;
322             OpensslEcPointFree(*ecPoint);
323             *ecPoint = NULL;
324             return HCF_ERR_CRYPTO_OPERATION;
325         }
326     }
327     return HCF_SUCCESS;
328 }
329 
FreeHcfBigInteger(HcfBigInteger * bigInt)330 static void FreeHcfBigInteger(HcfBigInteger *bigInt)
331 {
332     HcfFree(bigInt->data);
333     bigInt->data = NULL;
334     bigInt->len = 0;
335 }
336 
ConvertBigNumToEccPoint(const BIGNUM * x,const BIGNUM * y,HcfBigInteger * bigIntX,HcfBigInteger * bigIntY)337 static HcfResult ConvertBigNumToEccPoint(const BIGNUM *x, const BIGNUM *y,
338                                          HcfBigInteger *bigIntX, HcfBigInteger *bigIntY)
339 {
340     HcfResult ret = BigNumToBigInteger(x, bigIntX);
341     if (ret != HCF_SUCCESS) {
342         LOGE("Failed to convert XBIGNUM to HcfBigInteger.");
343         return ret;
344     }
345     ret = BigNumToBigInteger(y, bigIntY);
346     if (ret != HCF_SUCCESS) {
347         LOGE("Failed to convert YBIGNUM to HcfBigInteger.");
348         FreeHcfBigInteger(bigIntX);
349         return ret;
350     }
351     return HCF_SUCCESS;
352 }
353 
GetECCPointEncoded(const int32_t formatValue,EC_GROUP * ecGroup,EC_POINT * ecPoint,HcfBlob * returnBlob)354 static HcfResult GetECCPointEncoded(const int32_t formatValue, EC_GROUP *ecGroup,
355                                     EC_POINT *ecPoint, HcfBlob *returnBlob)
356 {
357     int32_t formatType = 0;
358     if (GetFormatTypeByFormatValue(formatValue, &formatType) != HCF_SUCCESS) {
359         LOGE("Failed to get formatType.");
360         return HCF_INVALID_PARAMS;
361     }
362 
363     size_t returnDataLen = EC_POINT_point2oct(ecGroup, ecPoint, formatType, NULL, 0, NULL);
364     if (returnDataLen == 0) {
365         LOGE("Failed to get encoded point length.");
366         HcfPrintOpensslError();
367         return HCF_ERR_CRYPTO_OPERATION;
368     }
369 
370     uint8_t *returnData = (uint8_t *)HcfMalloc(returnDataLen, 0);
371     if (returnData == NULL) {
372         LOGE("Failed to allocate memory for encoded point data.");
373         return HCF_ERR_MALLOC;
374     }
375     size_t result = EC_POINT_point2oct(ecGroup, ecPoint, formatType, returnData, returnDataLen, NULL);
376     if (result != returnDataLen) {
377         LOGE("Failed to get ECC point encoding.");
378         HcfPrintOpensslError();
379         HcfFree(returnData);
380         return HCF_ERR_CRYPTO_OPERATION;
381     }
382     returnBlob->data = returnData;
383     returnBlob->len = returnDataLen;
384     return HCF_SUCCESS;
385 }
386 
HcfEngineConvertPoint(const int32_t curveNameValue,HcfBlob * pointBlob,HcfPoint * returnPoint)387 HcfResult HcfEngineConvertPoint(const int32_t curveNameValue, HcfBlob *pointBlob, HcfPoint *returnPoint)
388 {
389     if ((curveNameValue == 0) || !HcfIsBlobValid(pointBlob) || (returnPoint == NULL)) {
390         LOGE("Invalid input parameter.");
391         return HCF_INVALID_PARAMS;
392     }
393     EC_GROUP *ecGroup = NULL;
394     EC_POINT *ecPoint = NULL;
395     BIGNUM *x = NULL;
396     BIGNUM *y = NULL;
397     HcfBigInteger tmpBigIntX = { .data = NULL, .len = 0 };
398     HcfBigInteger tmpBigIntY = { .data = NULL, .len = 0 };
399     HcfResult ret = HCF_SUCCESS;
400     do {
401         ret = InitEccPoint(curveNameValue, &ecGroup, &ecPoint, &x, &y);
402         if (ret != HCF_SUCCESS) {
403             LOGE("Failed to get EccPoint.");
404             break;
405         }
406         if (!OpensslEcOct2Point(ecGroup, ecPoint, pointBlob->data, pointBlob->len, NULL)) {
407             LOGE("Failed to convert pointBlob data to EC_POINT.");
408             HcfPrintOpensslError();
409             ret = HCF_ERR_CRYPTO_OPERATION;
410             break;
411         }
412         if (!OpensslEcPointGetAffineCoordinates(ecGroup, ecPoint, x, y, NULL)) {
413             LOGE("Failed to get affine coordinates from EC_POINT.");
414             ret = HCF_ERR_CRYPTO_OPERATION;
415             break;
416         }
417         ret = ConvertBigNumToEccPoint(x, y, &tmpBigIntX, &tmpBigIntY);
418         if (ret != HCF_SUCCESS) {
419             LOGE("Failed to convert BIGNUMs to HcfBigIntegers.");
420             break;
421         }
422         returnPoint->x = tmpBigIntX;
423         returnPoint->y = tmpBigIntY;
424     } while (0);
425     OpensslEcGroupFree(ecGroup);
426     OpensslEcPointFree(ecPoint);
427     OpensslBnFree(x);
428     OpensslBnFree(y);
429     return ret;
430 }
431 
HcfEngineGetEncodedPoint(const int32_t curveNameValue,HcfPoint * point,const int32_t formatValue,HcfBlob * returnBlob)432 HcfResult HcfEngineGetEncodedPoint(const int32_t curveNameValue, HcfPoint *point,
433                                    const int32_t formatValue, HcfBlob *returnBlob)
434 {
435     if ((curveNameValue == 0) || (point == NULL) || (formatValue == 0) || (returnBlob == NULL)) {
436         LOGE("Invalid input parameter.");
437         return HCF_INVALID_PARAMS;
438     }
439     EC_GROUP *ecGroup = NULL;
440     EC_POINT *ecPoint = NULL;
441     BIGNUM *bnX = NULL;
442     BIGNUM *bnY = NULL;
443     HcfResult ret = HCF_SUCCESS;
444     do {
445         ret = InitEccPoint(curveNameValue, &ecGroup, &ecPoint, NULL, NULL);
446         if (ret != HCF_SUCCESS) {
447             LOGE("Failed to get EccPoint.");
448             break;
449         }
450         ret = BigIntegerToBigNum(&(point->x), &bnX);
451         if (ret != HCF_SUCCESS) {
452             LOGE("Failed to convert HcfBigInteger to XBIGNUMs.");
453             break;
454         }
455         ret = BigIntegerToBigNum(&(point->y), &bnY);
456         if (ret != HCF_SUCCESS) {
457             LOGE("Failed to convert HcfBigInteger to YBIGNUMs.");
458             break;
459         }
460         if (OpensslEcPointSetAffineCoordinates(ecGroup, ecPoint, bnX, bnY, NULL) != HCF_OPENSSL_SUCCESS) {
461             LOGE("Failed to set point coordinates.");
462             HcfPrintOpensslError();
463             ret = HCF_ERR_CRYPTO_OPERATION;
464             break;
465         }
466         ret = GetECCPointEncoded(formatValue, ecGroup, ecPoint, returnBlob);
467         if (ret != HCF_SUCCESS) {
468             LOGE("Failed to get EccPointEncoded.");
469             break;
470         }
471     } while (0);
472     OpensslEcGroupFree(ecGroup);
473     OpensslEcPointFree(ecPoint);
474     OpensslBnFree(bnX);
475     OpensslBnFree(bnY);
476     return ret;
477 }
478