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 spi = NULL;
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 spi->paramsSpec.field = NULL;
190 HcfFree(spi);
191 spi = NULL;
192 return NULL;
193 }
194 spi->paramsSpec.field->fieldType = (char *)HcfMalloc(srcFieldTypeLen + 1, 0);
195 if (spi->paramsSpec.field->fieldType == NULL) {
196 LOGE("fieldType malloc failed.");
197 HcfFree(spi->paramsSpec.field);
198 spi->paramsSpec.field = NULL;
199 HcfFree(spi);
200 spi = NULL;
201 return NULL;
202 }
203
204 if (memcpy_s(spi->paramsSpec.field->fieldType, srcFieldTypeLen, fieldType, srcFieldTypeLen) != EOK) {
205 LOGE("memcpy fieldType failed.");
206 HcfFree(spi->paramsSpec.field->fieldType);
207 spi->paramsSpec.field->fieldType = NULL;
208 HcfFree(spi->paramsSpec.field);
209 spi->paramsSpec.field = NULL;
210 HcfFree(spi);
211 spi = NULL;
212 return NULL;
213 }
214 return spi;
215 }
216
FreeEccCommParamObject(HcfEccCommParamsSpecSpi * spec)217 static void FreeEccCommParamObject(HcfEccCommParamsSpecSpi *spec)
218 {
219 if (spec == NULL) {
220 LOGE("Invalid input parameter.");
221 return;
222 }
223 HcfFree(spec->paramsSpec.base.algName);
224 spec->paramsSpec.base.algName = NULL;
225 if (spec->paramsSpec.field != NULL) {
226 HcfECFieldFp *tmp = (HcfECFieldFp *)spec->paramsSpec.field;
227 HcfFree(tmp->p.data);
228 tmp->p.data = NULL;
229 HcfFree(spec->paramsSpec.field->fieldType);
230 spec->paramsSpec.field->fieldType = NULL;
231 HcfFree(spec->paramsSpec.field);
232 spec->paramsSpec.field = NULL;
233 }
234 HcfFree(spec->paramsSpec.a.data);
235 spec->paramsSpec.a.data = NULL;
236 HcfFree(spec->paramsSpec.b.data);
237 spec->paramsSpec.b.data = NULL;
238 HcfFree(spec->paramsSpec.n.data);
239 spec->paramsSpec.n.data = NULL;
240 HcfFree(spec->paramsSpec.g.x.data);
241 spec->paramsSpec.g.x.data = NULL;
242 HcfFree(spec->paramsSpec.g.y.data);
243 spec->paramsSpec.g.y.data = NULL;
244 HcfFree(spec);
245 }
246
HcfECCCommonParamSpecCreate(HcfAsyKeyGenParams * params,HcfEccCommParamsSpecSpi ** returnCommonParamSpec)247 HcfResult HcfECCCommonParamSpecCreate(HcfAsyKeyGenParams *params, HcfEccCommParamsSpecSpi **returnCommonParamSpec)
248 {
249 if ((params == NULL) || (returnCommonParamSpec == NULL)) {
250 LOGE("Invalid input parameter.");
251 return HCF_INVALID_PARAMS;
252 }
253 int32_t curveId = 0;
254 if (params->bits != 0) {
255 if (GetOpensslCurveId(params->bits, &curveId) != HCF_SUCCESS) {
256 LOGE("Get curveId parameter failed.");
257 return HCF_INVALID_PARAMS;
258 }
259 }
260 EC_GROUP *ecGroup = OpensslEcGroupNewByCurveName(curveId);
261 if (ecGroup == NULL) {
262 LOGE("Create ecGroup failed.");
263 return HCF_ERR_CRYPTO_OPERATION;
264 }
265 HcfEccCommParamsSpecSpi *object = BuildEccCommonParamObject();
266 if (object == NULL) {
267 LOGE("Build ecc common params object failed.");
268 OpensslEcGroupFree(ecGroup);
269 return HCF_ERR_MALLOC;
270 }
271 object->paramsSpec.base.specType = HCF_COMMON_PARAMS_SPEC;
272 if (GetAlgNameByBits(params->bits, &(object->paramsSpec.base.algName)) != HCF_SUCCESS) {
273 LOGE("Get algName parameter by bits failed.");
274 FreeEccCommParamObject(object);
275 object = NULL;
276 OpensslEcGroupFree(ecGroup);
277 return HCF_INVALID_PARAMS;
278 }
279 if (BuildCommonParam(ecGroup, object)!= HCF_SUCCESS) {
280 LOGE("Get common params failed.");
281 FreeEccCommParamObject(object);
282 object = NULL;
283 OpensslEcGroupFree(ecGroup);
284 return HCF_ERR_CRYPTO_OPERATION;
285 }
286 *returnCommonParamSpec = object;
287 OpensslEcGroupFree(ecGroup);
288 return HCF_SUCCESS;
289 }
290
InitEccPoint(const int32_t curveNameValue,EC_GROUP ** ecGroup,EC_POINT ** ecPoint,BIGNUM ** x,BIGNUM ** y)291 static HcfResult InitEccPoint(const int32_t curveNameValue, EC_GROUP **ecGroup,
292 EC_POINT **ecPoint, BIGNUM **x, BIGNUM **y)
293 {
294 int32_t nid = 0;
295 if (GetNidByCurveNameValue(curveNameValue, &nid) != HCF_SUCCESS) {
296 LOGE("Failed to get curveNameValue.");
297 return HCF_INVALID_PARAMS;
298 }
299 *ecGroup = OpensslEcGroupNewByCurveName(nid);
300 if (*ecGroup == NULL) {
301 LOGE("Failed to create EC group with nid %{public}d.", nid);
302 return HCF_ERR_CRYPTO_OPERATION;
303 }
304 *ecPoint = OpensslEcPointNew(*ecGroup);
305 if (*ecPoint == NULL) {
306 LOGE("Failed to allocate memory for EC_POINT.");
307 OpensslEcGroupFree(*ecGroup);
308 *ecGroup = NULL;
309 return HCF_ERR_CRYPTO_OPERATION;
310 }
311 if (x != NULL) {
312 *x = OpensslBnNew();
313 if (*x == NULL) {
314 LOGE("Failed to allocate memory for BIGNUM x.");
315 OpensslEcGroupFree(*ecGroup);
316 *ecGroup = NULL;
317 OpensslEcPointFree(*ecPoint);
318 *ecPoint = NULL;
319 return HCF_ERR_CRYPTO_OPERATION;
320 }
321 }
322 if (y != NULL) {
323 *y = OpensslBnNew();
324 if (*y == NULL) {
325 LOGE("Failed to allocate memory for BIGNUM y.");
326 OpensslBnFree(*x);
327 *x = NULL;
328 OpensslEcGroupFree(*ecGroup);
329 *ecGroup = NULL;
330 OpensslEcPointFree(*ecPoint);
331 *ecPoint = NULL;
332 return HCF_ERR_CRYPTO_OPERATION;
333 }
334 }
335 return HCF_SUCCESS;
336 }
337
FreeHcfBigInteger(HcfBigInteger * bigInt)338 static void FreeHcfBigInteger(HcfBigInteger *bigInt)
339 {
340 HcfFree(bigInt->data);
341 bigInt->data = NULL;
342 bigInt->len = 0;
343 }
344
ConvertBigNumToEccPoint(const BIGNUM * x,const BIGNUM * y,HcfBigInteger * bigIntX,HcfBigInteger * bigIntY)345 static HcfResult ConvertBigNumToEccPoint(const BIGNUM *x, const BIGNUM *y,
346 HcfBigInteger *bigIntX, HcfBigInteger *bigIntY)
347 {
348 HcfResult ret = BigNumToBigInteger(x, bigIntX);
349 if (ret != HCF_SUCCESS) {
350 LOGE("Failed to convert XBIGNUM to HcfBigInteger.");
351 return ret;
352 }
353 ret = BigNumToBigInteger(y, bigIntY);
354 if (ret != HCF_SUCCESS) {
355 LOGE("Failed to convert YBIGNUM to HcfBigInteger.");
356 FreeHcfBigInteger(bigIntX);
357 return ret;
358 }
359 return HCF_SUCCESS;
360 }
361
GetECCPointEncoded(const int32_t formatValue,EC_GROUP * ecGroup,EC_POINT * ecPoint,HcfBlob * returnBlob)362 static HcfResult GetECCPointEncoded(const int32_t formatValue, EC_GROUP *ecGroup,
363 EC_POINT *ecPoint, HcfBlob *returnBlob)
364 {
365 int32_t formatType = 0;
366 if (GetFormatTypeByFormatValue(formatValue, &formatType) != HCF_SUCCESS) {
367 LOGE("Failed to get formatType.");
368 return HCF_INVALID_PARAMS;
369 }
370
371 size_t returnDataLen = EC_POINT_point2oct(ecGroup, ecPoint, formatType, NULL, 0, NULL);
372 if (returnDataLen == 0) {
373 LOGE("Failed to get encoded point length.");
374 HcfPrintOpensslError();
375 return HCF_ERR_CRYPTO_OPERATION;
376 }
377
378 uint8_t *returnData = (uint8_t *)HcfMalloc(returnDataLen, 0);
379 if (returnData == NULL) {
380 LOGE("Failed to allocate memory for encoded point data.");
381 return HCF_ERR_MALLOC;
382 }
383 size_t result = EC_POINT_point2oct(ecGroup, ecPoint, formatType, returnData, returnDataLen, NULL);
384 if (result != returnDataLen) {
385 LOGE("Failed to get ECC point encoding.");
386 HcfPrintOpensslError();
387 HcfFree(returnData);
388 returnData = NULL;
389 return HCF_ERR_CRYPTO_OPERATION;
390 }
391 returnBlob->data = returnData;
392 returnBlob->len = returnDataLen;
393 return HCF_SUCCESS;
394 }
395
HcfEngineConvertPoint(const int32_t curveNameValue,HcfBlob * pointBlob,HcfPoint * returnPoint)396 HcfResult HcfEngineConvertPoint(const int32_t curveNameValue, HcfBlob *pointBlob, HcfPoint *returnPoint)
397 {
398 if ((curveNameValue == 0) || !HcfIsBlobValid(pointBlob) || (returnPoint == NULL)) {
399 LOGE("Invalid input parameter.");
400 return HCF_INVALID_PARAMS;
401 }
402 EC_GROUP *ecGroup = NULL;
403 EC_POINT *ecPoint = NULL;
404 BIGNUM *x = NULL;
405 BIGNUM *y = NULL;
406 HcfBigInteger tmpBigIntX = { .data = NULL, .len = 0 };
407 HcfBigInteger tmpBigIntY = { .data = NULL, .len = 0 };
408 HcfResult ret = HCF_SUCCESS;
409 do {
410 ret = InitEccPoint(curveNameValue, &ecGroup, &ecPoint, &x, &y);
411 if (ret != HCF_SUCCESS) {
412 LOGE("Failed to get EccPoint.");
413 break;
414 }
415 if (!OpensslEcOct2Point(ecGroup, ecPoint, pointBlob->data, pointBlob->len, NULL)) {
416 LOGE("Failed to convert pointBlob data to EC_POINT.");
417 HcfPrintOpensslError();
418 ret = HCF_ERR_CRYPTO_OPERATION;
419 break;
420 }
421 if (!OpensslEcPointGetAffineCoordinates(ecGroup, ecPoint, x, y, NULL)) {
422 LOGE("Failed to get affine coordinates from EC_POINT.");
423 ret = HCF_ERR_CRYPTO_OPERATION;
424 break;
425 }
426 ret = ConvertBigNumToEccPoint(x, y, &tmpBigIntX, &tmpBigIntY);
427 if (ret != HCF_SUCCESS) {
428 LOGE("Failed to convert BIGNUMs to HcfBigIntegers.");
429 break;
430 }
431 returnPoint->x = tmpBigIntX;
432 returnPoint->y = tmpBigIntY;
433 } while (0);
434 OpensslEcGroupFree(ecGroup);
435 OpensslEcPointFree(ecPoint);
436 OpensslBnFree(x);
437 OpensslBnFree(y);
438 return ret;
439 }
440
HcfEngineGetEncodedPoint(const int32_t curveNameValue,HcfPoint * point,const int32_t formatValue,HcfBlob * returnBlob)441 HcfResult HcfEngineGetEncodedPoint(const int32_t curveNameValue, HcfPoint *point,
442 const int32_t formatValue, HcfBlob *returnBlob)
443 {
444 if ((curveNameValue == 0) || (point == NULL) || (formatValue == 0) || (returnBlob == NULL)) {
445 LOGE("Invalid input parameter.");
446 return HCF_INVALID_PARAMS;
447 }
448 EC_GROUP *ecGroup = NULL;
449 EC_POINT *ecPoint = NULL;
450 BIGNUM *bnX = NULL;
451 BIGNUM *bnY = NULL;
452 HcfResult ret = HCF_SUCCESS;
453 do {
454 ret = InitEccPoint(curveNameValue, &ecGroup, &ecPoint, NULL, NULL);
455 if (ret != HCF_SUCCESS) {
456 LOGE("Failed to get EccPoint.");
457 break;
458 }
459 ret = BigIntegerToBigNum(&(point->x), &bnX);
460 if (ret != HCF_SUCCESS) {
461 LOGE("Failed to convert HcfBigInteger to XBIGNUMs.");
462 break;
463 }
464 ret = BigIntegerToBigNum(&(point->y), &bnY);
465 if (ret != HCF_SUCCESS) {
466 LOGE("Failed to convert HcfBigInteger to YBIGNUMs.");
467 break;
468 }
469 if (OpensslEcPointSetAffineCoordinates(ecGroup, ecPoint, bnX, bnY, NULL) != HCF_OPENSSL_SUCCESS) {
470 LOGE("Failed to set point coordinates.");
471 HcfPrintOpensslError();
472 ret = HCF_ERR_CRYPTO_OPERATION;
473 break;
474 }
475 ret = GetECCPointEncoded(formatValue, ecGroup, ecPoint, returnBlob);
476 if (ret != HCF_SUCCESS) {
477 LOGE("Failed to get EccPointEncoded.");
478 break;
479 }
480 } while (0);
481 OpensslEcGroupFree(ecGroup);
482 OpensslEcPointFree(ecPoint);
483 OpensslBnFree(bnX);
484 OpensslBnFree(bnY);
485 return ret;
486 }
487