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 = OpensslEcKeyNewByCurveName(curveId);
27 if (ecKey == NULL) {
28 LOGD("[error] new ec key failed.");
29 return HCF_ERR_CRYPTO_OPERATION;
30 }
31 if (OpensslEcKeyGenerateKey(ecKey) <= 0) {
32 LOGD("[error] generate ec key failed.");
33 OpensslEcKeyFree(ecKey);
34 return HCF_ERR_CRYPTO_OPERATION;
35 }
36 if (OpensslEcKeyCheckKey(ecKey) <= 0) {
37 LOGD("[error] check key fail.");
38 OpensslEcKeyFree(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 OpensslBnFree(pStd);
48 OpensslBnFree(bStd);
49 OpensslBnFree(xStd);
50 OpensslBnFree(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 = OpensslEcGroupNewCurveGfp(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 OpensslBnFree(p);
77 OpensslBnFree(a);
78 OpensslBnFree(b);
79
80 if (ret == HCF_SUCCESS) {
81 *ecGroup = group;
82 return ret;
83 }
84 OpensslEcGroupFree(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 = OpensslBnNew();
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 !OpensslBnSetWord(cofactor, (uint32_t)ecParams->h)) {
105 LOGD("[error] BigInteger to BigNum failed.");
106 ret = HCF_ERR_CRYPTO_OPERATION;
107 break;
108 }
109 generator = OpensslEcPointNew(group);
110 if (generator == NULL) {
111 LOGE("Alloc group memory failed.");
112 ret = HCF_ERR_CRYPTO_OPERATION;
113 break;
114 }
115 if (!OpensslEcPointSetAffineCoordinatesGfp(group, generator, x, y, ctx)) {
116 LOGD("[error] OpensslEcPointSetAffineCoordinatesGfp failed.");
117 ret = HCF_ERR_CRYPTO_OPERATION;
118 HcfPrintOpensslError();
119 break;
120 }
121
122 if (!OpensslEcGroupSetGenerator(group, generator, order, cofactor)) {
123 LOGD("[error] OpensslEcGroupSetGenerator failed.");
124 ret = HCF_ERR_CRYPTO_OPERATION;
125 HcfPrintOpensslError();
126 break;
127 }
128 } while (0);
129 OpensslBnFree(x);
130 OpensslBnFree(y);
131 OpensslBnFree(order);
132 OpensslBnFree(cofactor);
133 OpensslEcPointFree(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 = OpensslBnCtxNew();
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 OpensslBnCtxFree(ctx);
153 return ret;
154 }
155 ret = SetEcPointToGroup(ecParams, group, ctx);
156 if (ret != HCF_SUCCESS) {
157 OpensslBnCtxFree(ctx);
158 OpensslEcGroupFree(group);
159 LOGD("[error] Set Ec point fail");
160 return ret;
161 }
162 OpensslBnCtxFree(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 = OpensslEcKeyGet0Group(ecKey);
170 if (group == NULL) {
171 LOGD("[error] Not find group from ecKey.");
172 return HCF_ERR_CRYPTO_OPERATION;
173 }
174 EC_POINT *point = OpensslEcPointNew(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 OpensslEcPointFree(point);
185 OpensslBnFree(pkX);
186 OpensslBnFree(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)OpensslEcPointSetAffineCoordinatesGfp(group, point, pkX, pkY, NULL);
193 OpensslBnFree(pkX);
194 OpensslBnFree(pkY);
195
196 if (ret != HCF_OPENSSL_SUCCESS) {
197 LOGD("[error] OpensslEcPointSetAffineCoordinatesGfp failed.");
198 OpensslEcPointFree(point);
199 return HCF_ERR_CRYPTO_OPERATION;
200 }
201 ret = OpensslEcKeySetPublicKey(ecKey, point);
202 if (ret != HCF_OPENSSL_SUCCESS) {
203 LOGD("[error] OpensslEcKeySetPublicKey failed.");
204 OpensslEcPointFree(point);
205 return HCF_ERR_CRYPTO_OPERATION;
206 }
207 OpensslEcPointFree(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)OpensslEcKeySetPrivateKey(ecKey, sk);
219 if (ret != HCF_OPENSSL_SUCCESS) {
220 LOGD("[error] OpensslEcKeySetPrivateKey failed.");
221 OpensslBnClearFree(sk);
222 return HCF_ERR_CRYPTO_OPERATION;
223 }
224 OpensslBnClearFree(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 = OpensslEcKeyGet0Group(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 = OpensslEcPointNew(group);
242 do {
243 if (point == NULL) {
244 LOGD("[error] OpensslEcPointNew failed.");
245 ret = HCF_ERR_CRYPTO_OPERATION;
246 break;
247 }
248 if (!OpensslEcPointMul(group, point, sk, NULL, NULL, NULL)) {
249 LOGD("[error] EC_POINT_mul failed.");
250 ret = HCF_ERR_CRYPTO_OPERATION;
251 break;
252 }
253 if (!OpensslEcKeySetPublicKey(ecKey, point)) {
254 LOGD("[error] OpensslEcKeySetPublicKey failed.");
255 ret = HCF_ERR_CRYPTO_OPERATION;
256 }
257 } while (0);
258 OpensslEcPointFree(point);
259 OpensslBnClearFree(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 = OpensslBnNew();
293 BIGNUM *a = OpensslBnNew();
294 BIGNUM *b = OpensslBnNew();
295 if (p == NULL || a == NULL || b == NULL) {
296 LOGD("[error] new BN failed.");
297 OpensslBnFree(p);
298 OpensslBnFree(a);
299 OpensslBnFree(b);
300 return HCF_ERR_CRYPTO_OPERATION;
301 }
302
303 if (OpensslEcGroupGetCurveGfp(group, p, a, b, NULL) != HCF_OPENSSL_SUCCESS) {
304 LOGD("[error] OpensslEcGroupGetCurveGfp failed.");
305 OpensslBnFree(p);
306 OpensslBnFree(a);
307 OpensslBnFree(b);
308 return HCF_ERR_CRYPTO_OPERATION;
309 }
310
311 HcfResult ret = HCF_INVALID_PARAMS;
312 int curveId = OpensslEcGroupGetCurveName(group);
313 if (curveId == NID_secp256k1 && item == ECC_A_BN) {
314 ret = BigNumToBigIntegerSecp256k1(a, returnBigInteger);
315 OpensslBnFree(p);
316 OpensslBnFree(a);
317 OpensslBnFree(b);
318 return ret;
319 }
320 switch (item) {
321 case ECC_FP_P_BN:
322 ret = BigNumToBigInteger(p, returnBigInteger);
323 break;
324 case ECC_A_BN:
325 ret = BigNumToBigInteger(a, returnBigInteger);
326 break;
327 case ECC_B_BN:
328 ret = BigNumToBigInteger(b, returnBigInteger);
329 break;
330 default:
331 LOGD("[error] Invalid ecc key big number spec!");
332 break;
333 }
334 OpensslBnFree(p);
335 OpensslBnFree(a);
336 OpensslBnFree(b);
337 return ret;
338 }
339
GetGenerator(const EC_GROUP * group,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)340 HcfResult GetGenerator(const EC_GROUP *group, const AsyKeySpecItem item, HcfBigInteger *returnBigInteger)
341 {
342 const EC_POINT *generator = OpensslEcGroupGet0Generator(group);
343 if (generator == NULL) {
344 LOGD("[error] OpensslEcGroupGet0Generator failed.");
345 return HCF_ERR_CRYPTO_OPERATION;
346 }
347
348 BIGNUM *gX = OpensslBnNew();
349 BIGNUM *gY = OpensslBnNew();
350 if (gX == NULL || gY == NULL) {
351 LOGD("[error] new BN failed.");
352 OpensslBnFree(gX);
353 OpensslBnFree(gY);
354 return HCF_ERR_CRYPTO_OPERATION;
355 }
356
357 if (OpensslEcPointGetAffineCoordinatesGfp(group, generator, gX, gY, NULL) != HCF_OPENSSL_SUCCESS) {
358 LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
359 OpensslBnFree(gX);
360 OpensslBnFree(gY);
361 return HCF_ERR_CRYPTO_OPERATION;
362 }
363
364 HcfResult ret = HCF_INVALID_PARAMS;
365 switch (item) {
366 case ECC_G_X_BN:
367 ret = BigNumToBigInteger(gX, returnBigInteger);
368 break;
369 case ECC_G_Y_BN:
370 ret = BigNumToBigInteger(gY, returnBigInteger);
371 break;
372 default:
373 LOGE("Invalid ecc key big number spec!");
374 break;
375 }
376 OpensslBnFree(gX);
377 OpensslBnFree(gY);
378 return ret;
379 }
380
GetOrder(const EC_GROUP * group,HcfBigInteger * returnBigInteger)381 HcfResult GetOrder(const EC_GROUP *group, HcfBigInteger *returnBigInteger)
382 {
383 BIGNUM *order = OpensslBnNew();
384 if (order == NULL) {
385 LOGD("[error] new BN failed.");
386 return HCF_ERR_CRYPTO_OPERATION;
387 }
388
389 if (OpensslEcGroupGetOrder(group, order, NULL) != HCF_OPENSSL_SUCCESS) {
390 LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
391 OpensslBnFree(order);
392 return HCF_ERR_CRYPTO_OPERATION;
393 }
394
395 HcfResult ret = BigNumToBigInteger(order, returnBigInteger);
396 OpensslBnFree(order);
397 return ret;
398 }
399
GetCofactor(const EC_GROUP * group,int * returnCofactor)400 HcfResult GetCofactor(const EC_GROUP *group, int *returnCofactor)
401 {
402 BIGNUM *cofactor = OpensslBnNew();
403 if (cofactor == NULL) {
404 LOGD("[error] new BN failed.");
405 return HCF_ERR_CRYPTO_OPERATION;
406 }
407
408 if (OpensslEcGroupGetCofactor(group, cofactor, NULL) != HCF_OPENSSL_SUCCESS) {
409 LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
410 OpensslBnFree(cofactor);
411 return HCF_ERR_CRYPTO_OPERATION;
412 }
413
414 *returnCofactor = (int)(OpensslBnGetWord(cofactor));
415 // cofactor should not be zero.
416 if (*returnCofactor == 0) {
417 LOGD("[error] OpensslBnGetWord failed.");
418 OpensslBnFree(cofactor);
419 return HCF_ERR_CRYPTO_OPERATION;
420 }
421 OpensslBnFree(cofactor);
422 return HCF_SUCCESS;
423 }
424
GetFieldSize(const EC_GROUP * group,int32_t * fieldSize)425 HcfResult GetFieldSize(const EC_GROUP *group, int32_t *fieldSize)
426 {
427 *fieldSize = OpensslEcGroupGetDegree(group);
428 if (*fieldSize == 0) {
429 LOGD("[error] OpensslEcGroupGetDegree failed.");
430 return HCF_ERR_CRYPTO_OPERATION;
431 }
432 return HCF_SUCCESS;
433 }
434
GetFieldType(const HcfKey * self,const bool isPrivate,char ** returnString)435 HcfResult GetFieldType(const HcfKey *self, const bool isPrivate, char **returnString)
436 {
437 char *fieldType = NULL;
438 if (isPrivate) {
439 fieldType = ((HcfOpensslEccPriKey *)self)->fieldType;
440 } else {
441 fieldType = ((HcfOpensslEccPubKey *)self)->fieldType;
442 }
443
444 if (fieldType == NULL) {
445 LOGE("No fieldType in EccPubKey struct.");
446 return HCF_INVALID_PARAMS;
447 }
448
449 size_t len = HcfStrlen(fieldType);
450 if (len == 0) {
451 LOGE("fieldType is empty!");
452 return HCF_INVALID_PARAMS;
453 }
454 *returnString = (char *)HcfMalloc(len + 1, 0);
455 if (*returnString == NULL) {
456 LOGE("Alloc returnString memory failed.");
457 return HCF_ERR_MALLOC;
458 }
459 (void)memcpy_s(*returnString, len, fieldType, len);
460
461 return HCF_SUCCESS;
462 }
463
GetPubKeyXOrY(const EC_GROUP * group,const EC_POINT * point,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)464 static HcfResult GetPubKeyXOrY(const EC_GROUP *group, const EC_POINT *point, const AsyKeySpecItem item,
465 HcfBigInteger *returnBigInteger)
466 {
467 BIGNUM *pkX = OpensslBnNew();
468 BIGNUM *pkY = OpensslBnNew();
469 if (pkX == NULL || pkY == NULL) {
470 LOGD("[error] new BN failed.");
471 OpensslBnFree(pkX);
472 OpensslBnFree(pkY);
473 return HCF_ERR_CRYPTO_OPERATION;
474 }
475
476 if (OpensslEcPointGetAffineCoordinatesGfp(group, point, pkX, pkY, NULL) != HCF_OPENSSL_SUCCESS) {
477 LOGD("[error] OpensslEcPointGetAffineCoordinatesGfp failed.");
478 OpensslBnFree(pkX);
479 OpensslBnFree(pkY);
480 return HCF_ERR_CRYPTO_OPERATION;
481 }
482
483 HcfResult ret = HCF_INVALID_PARAMS;
484 switch (item) {
485 case ECC_PK_X_BN:
486 ret = BigNumToBigInteger(pkX, returnBigInteger);
487 break;
488 case ECC_PK_Y_BN:
489 ret = BigNumToBigInteger(pkY, returnBigInteger);
490 break;
491 default:
492 LOGD("[error] Invalid ecc key big number spec!");
493 break;
494 }
495 OpensslBnFree(pkX);
496 OpensslBnFree(pkY);
497 return ret;
498 }
499
GetPkSkBigInteger(const HcfKey * self,bool isPrivate,const AsyKeySpecItem item,HcfBigInteger * returnBigInteger)500 HcfResult GetPkSkBigInteger(const HcfKey *self, bool isPrivate,
501 const AsyKeySpecItem item, HcfBigInteger *returnBigInteger)
502 {
503 HcfResult ret = HCF_INVALID_PARAMS;
504 if (item == ECC_SK_BN) {
505 if (!isPrivate) {
506 LOGD("[error] ecc pub key has no private key spec item");
507 return ret;
508 }
509 ret = BigNumToBigInteger(OpensslEcKeyGet0PrivateKey(((HcfOpensslEccPriKey *)self)->ecKey),
510 returnBigInteger);
511 } else {
512 if (isPrivate) {
513 LOGD("[error] ecc pri key cannot get pub key spec item");
514 return ret;
515 }
516 ret = GetPubKeyXOrY(OpensslEcKeyGet0Group(((HcfOpensslEccPubKey *)self)->ecKey),
517 OpensslEcKeyGet0PublicKey(((HcfOpensslEccPubKey *)self)->ecKey), item, returnBigInteger);
518 }
519 return ret;
520 }
521