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