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