1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_ELGAMAL
18
19 #include "crypt_elgamal.h"
20 #include "elgamal_local.h"
21 #include "crypt_errno.h"
22 #include "crypt_utils.h"
23 #include "securec.h"
24 #include "bsl_sal.h"
25 #include "bsl_err_internal.h"
26 #include "crypt_params_key.h"
27
CRYPT_ELGAMAL_NewCtx(void)28 CRYPT_ELGAMAL_Ctx *CRYPT_ELGAMAL_NewCtx(void)
29 {
30 CRYPT_ELGAMAL_Ctx *ctx = NULL;
31 ctx = (CRYPT_ELGAMAL_Ctx *)BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_Ctx));
32 if (ctx == NULL) {
33 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
34 return NULL;
35 }
36
37 (void)memset_s(ctx, sizeof(CRYPT_ELGAMAL_Ctx), 0, sizeof(CRYPT_ELGAMAL_Ctx));
38 BSL_SAL_ReferencesInit(&(ctx->references));
39
40 return ctx;
41 }
42
CRYPT_ELGAMAL_NewCtxEx(void * libCtx)43 CRYPT_ELGAMAL_Ctx *CRYPT_ELGAMAL_NewCtxEx(void *libCtx)
44 {
45 CRYPT_ELGAMAL_Ctx *ctx = CRYPT_ELGAMAL_NewCtx();
46 if (ctx == NULL) {
47 return NULL;
48 }
49 ctx->libCtx = libCtx;
50 return ctx;
51 }
52
ElGamalPubKeyDupCtx(CRYPT_ELGAMAL_PubKey * pubKey)53 static CRYPT_ELGAMAL_PubKey *ElGamalPubKeyDupCtx(CRYPT_ELGAMAL_PubKey *pubKey)
54 {
55 CRYPT_ELGAMAL_PubKey *newPubKey = (CRYPT_ELGAMAL_PubKey *)BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_PubKey));
56 if (newPubKey == NULL) {
57 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
58 return NULL;
59 }
60
61 (void)memset_s(newPubKey, sizeof(CRYPT_ELGAMAL_PubKey), 0, sizeof(CRYPT_ELGAMAL_PubKey));
62
63 GOTO_ERR_IF_SRC_NOT_NULL(newPubKey->p, pubKey->p, BN_Dup(pubKey->p), CRYPT_MEM_ALLOC_FAIL);
64 GOTO_ERR_IF_SRC_NOT_NULL(newPubKey->g, pubKey->g, BN_Dup(pubKey->g), CRYPT_MEM_ALLOC_FAIL);
65 GOTO_ERR_IF_SRC_NOT_NULL(newPubKey->y, pubKey->y, BN_Dup(pubKey->y), CRYPT_MEM_ALLOC_FAIL);
66 GOTO_ERR_IF_SRC_NOT_NULL(newPubKey->q, pubKey->q, BN_Dup(pubKey->q), CRYPT_MEM_ALLOC_FAIL);
67
68 return newPubKey;
69 ERR:
70 ELGAMAL_FREE_PUB_KEY(newPubKey);
71 return NULL;
72 }
73
ElGamalPrvKeyDupCtx(CRYPT_ELGAMAL_PrvKey * prvKey)74 static CRYPT_ELGAMAL_PrvKey *ElGamalPrvKeyDupCtx(CRYPT_ELGAMAL_PrvKey *prvKey)
75 {
76 CRYPT_ELGAMAL_PrvKey *newPrvKey = (CRYPT_ELGAMAL_PrvKey *)BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_PrvKey));
77 if (newPrvKey == NULL) {
78 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
79 return NULL;
80 }
81
82 (void)memset_s(newPrvKey, sizeof(CRYPT_ELGAMAL_PrvKey), 0, sizeof(CRYPT_ELGAMAL_PrvKey));
83
84 GOTO_ERR_IF_SRC_NOT_NULL(newPrvKey->p, prvKey->p, BN_Dup(prvKey->p), CRYPT_MEM_ALLOC_FAIL);
85 GOTO_ERR_IF_SRC_NOT_NULL(newPrvKey->g, prvKey->g, BN_Dup(prvKey->g), CRYPT_MEM_ALLOC_FAIL);
86 GOTO_ERR_IF_SRC_NOT_NULL(newPrvKey->x, prvKey->x, BN_Dup(prvKey->x), CRYPT_MEM_ALLOC_FAIL);
87
88 return newPrvKey;
89 ERR:
90 ELGAMAL_FREE_PRV_KEY(newPrvKey);
91 return NULL;
92 }
93
ElGamalParaDupCtx(CRYPT_ELGAMAL_Para * para)94 static CRYPT_ELGAMAL_Para *ElGamalParaDupCtx(CRYPT_ELGAMAL_Para *para)
95 {
96 CRYPT_ELGAMAL_Para *newPara = (CRYPT_ELGAMAL_Para *)BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_Para));
97 if (newPara == NULL) {
98 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
99 return NULL;
100 }
101
102 (void)memset_s(newPara, sizeof(CRYPT_ELGAMAL_Para), 0, sizeof(CRYPT_ELGAMAL_Para));
103
104 newPara->bits = para->bits;
105 GOTO_ERR_IF_SRC_NOT_NULL(newPara->q, para->q, BN_Dup(para->q), CRYPT_MEM_ALLOC_FAIL);
106
107 return newPara;
108 ERR:
109 ELGAMAL_FREE_PARA(newPara);
110 return NULL;
111 }
112
CRYPT_ELGAMAL_DupCtx(CRYPT_ELGAMAL_Ctx * keyCtx)113 CRYPT_ELGAMAL_Ctx *CRYPT_ELGAMAL_DupCtx(CRYPT_ELGAMAL_Ctx *keyCtx)
114 {
115 if (keyCtx == NULL) {
116 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
117 return NULL;
118 }
119
120 CRYPT_ELGAMAL_Ctx *newKeyCtx = BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_Ctx));;
121 if (newKeyCtx == NULL) {
122 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
123 return NULL;
124 }
125
126 (void)memset_s(newKeyCtx, sizeof(CRYPT_ELGAMAL_Ctx), 0, sizeof(CRYPT_ELGAMAL_Ctx));
127
128 GOTO_ERR_IF_SRC_NOT_NULL(newKeyCtx->prvKey, keyCtx->prvKey, ElGamalPrvKeyDupCtx(keyCtx->prvKey),
129 CRYPT_MEM_ALLOC_FAIL);
130 GOTO_ERR_IF_SRC_NOT_NULL(newKeyCtx->pubKey, keyCtx->pubKey, ElGamalPubKeyDupCtx(keyCtx->pubKey),
131 CRYPT_MEM_ALLOC_FAIL);
132 GOTO_ERR_IF_SRC_NOT_NULL(newKeyCtx->para, keyCtx->para, ElGamalParaDupCtx(keyCtx->para), CRYPT_MEM_ALLOC_FAIL);
133 BSL_SAL_ReferencesInit(&(newKeyCtx->references));
134
135 return newKeyCtx;
136 ERR:
137 CRYPT_ELGAMAL_FreeCtx(newKeyCtx);
138 return NULL;
139 }
140
GetElGamalParam(const BSL_Param * params,int32_t type,const uint8_t ** value,uint32_t * valueLen)141 static int32_t GetElGamalParam(const BSL_Param *params, int32_t type, const uint8_t **value, uint32_t *valueLen)
142 {
143 const BSL_Param *temp = BSL_PARAM_FindConstParam(params, type);
144 if (temp == NULL || temp->valueLen == 0 || temp->value == NULL) {
145 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
146 return CRYPT_INVALID_ARG;
147 }
148
149 *value = temp->value;
150 *valueLen = temp->valueLen;
151
152 return CRYPT_SUCCESS;
153 }
154
GetElGamalBits(const BSL_Param * params,uint32_t * bits)155 static int32_t GetElGamalBits(const BSL_Param *params, uint32_t *bits)
156 {
157 uint32_t bitsLen = sizeof(*bits);
158 const BSL_Param *temp = BSL_PARAM_FindConstParam(params, CRYPT_PARAM_ELGAMAL_BITS);
159 if (temp == NULL) {
160 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
161 return CRYPT_INVALID_ARG;
162 }
163
164 int32_t ret = BSL_PARAM_GetValue(temp, CRYPT_PARAM_ELGAMAL_BITS, BSL_PARAM_TYPE_UINT32, bits, &bitsLen);
165 if (ret != BSL_SUCCESS || *bits == 0 || *bits > ELGAMAL_MAX_MODULUS_BITS) {
166 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
167 return CRYPT_INVALID_ARG;
168 }
169
170 return CRYPT_SUCCESS;
171 }
172
GetElGamalKBits(const BSL_Param * params,uint32_t * k_bits)173 static int32_t GetElGamalKBits(const BSL_Param *params, uint32_t *k_bits)
174 {
175 uint32_t kLen = sizeof(*k_bits);
176 const BSL_Param *temp = BSL_PARAM_FindConstParam(params, CRYPT_PARAM_ELGAMAL_KBITS);
177 if (temp == NULL) {
178 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
179 return CRYPT_INVALID_ARG;
180 }
181
182 int32_t ret = BSL_PARAM_GetValue(temp, CRYPT_PARAM_ELGAMAL_KBITS, BSL_PARAM_TYPE_UINT32, k_bits, &kLen);
183 if (ret != BSL_SUCCESS || *k_bits == 0 || *k_bits > ELGAMAL_MAX_MODULUS_BITS) {
184 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
185 return CRYPT_INVALID_ARG;
186 }
187
188 return CRYPT_SUCCESS;
189 }
190
ValidateElGamalParams(uint32_t qLen,uint32_t k_bits)191 static int32_t ValidateElGamalParams(uint32_t qLen, uint32_t k_bits)
192 {
193 if (qLen != BN_BITS_TO_BYTES(k_bits)) {
194 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_KEY_KBITS);
195 return CRYPT_ELGAMAL_ERR_KEY_KBITS;
196 }
197
198 return CRYPT_SUCCESS;
199 }
200
CRYPT_ELGAMAL_NewPara(const BSL_Param * params)201 CRYPT_ELGAMAL_Para *CRYPT_ELGAMAL_NewPara(const BSL_Param *params)
202 {
203 if (params == NULL) {
204 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
205 return NULL;
206 }
207
208 const uint8_t *q = NULL;
209 uint32_t qLen = 0;
210 int32_t ret = GetElGamalParam(params, CRYPT_PARAM_ELGAMAL_Q, &q, &qLen);
211 if (ret != CRYPT_SUCCESS) {
212 return NULL;
213 }
214
215 uint32_t bits = 0;
216 ret = GetElGamalBits(params, &bits);
217 if (ret != CRYPT_SUCCESS) {
218 return NULL;
219 }
220
221 uint32_t k_bits = 0;
222 ret = GetElGamalKBits(params, &k_bits);
223 if (ret != CRYPT_SUCCESS) {
224 return NULL;
225 }
226
227 ret = ValidateElGamalParams(qLen, k_bits);
228 if (ret != CRYPT_SUCCESS) {
229 return NULL;
230 }
231
232 CRYPT_ELGAMAL_Para *retPara = BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_Para));
233 if (retPara == NULL) {
234 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
235 return NULL;
236 }
237
238 retPara->bits = bits;
239 retPara->k_bits = k_bits;
240 retPara->q = BN_Create(k_bits);
241 if (retPara->q == NULL) {
242 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
243 CRYPT_ELGAMAL_FreePara(retPara);
244 return NULL;
245 }
246
247 return retPara;
248 }
249
CRYPT_ELGAMAL_FreeCtx(CRYPT_ELGAMAL_Ctx * ctx)250 void CRYPT_ELGAMAL_FreeCtx(CRYPT_ELGAMAL_Ctx *ctx)
251 {
252 if (ctx == NULL) {
253 return;
254 }
255
256 int i = 0;
257 BSL_SAL_AtomicDownReferences(&(ctx->references), &i);
258 if (i > 0) {
259 return;
260 }
261
262 BSL_SAL_ReferencesFree(&(ctx->references));
263 ELGAMAL_FREE_PRV_KEY(ctx->prvKey);
264 ELGAMAL_FREE_PUB_KEY(ctx->pubKey);
265 ELGAMAL_FREE_PARA(ctx->para);
266 BSL_SAL_Free(ctx);
267 }
268
CRYPT_ELGAMAL_FreePara(CRYPT_ELGAMAL_Para * para)269 void CRYPT_ELGAMAL_FreePara(CRYPT_ELGAMAL_Para *para)
270 {
271 if (para == NULL) {
272 return;
273 }
274 BN_Destroy(para->q);
275 BSL_SAL_Free(para);
276 }
277
ELGAMAL_FreePrvKey(CRYPT_ELGAMAL_PrvKey * prvKey)278 void ELGAMAL_FreePrvKey(CRYPT_ELGAMAL_PrvKey *prvKey)
279 {
280 if (prvKey == NULL) {
281 return;
282 }
283 BN_Destroy(prvKey->p);
284 BN_Destroy(prvKey->g);
285 BN_Destroy(prvKey->x);
286 BSL_SAL_Free(prvKey);
287 }
288
ELGAMAL_FreePubKey(CRYPT_ELGAMAL_PubKey * pubKey)289 void ELGAMAL_FreePubKey(CRYPT_ELGAMAL_PubKey *pubKey)
290 {
291 if (pubKey == NULL) {
292 return;
293 }
294 BN_Destroy(pubKey->p);
295 BN_Destroy(pubKey->q);
296 BN_Destroy(pubKey->g);
297 BN_Destroy(pubKey->y);
298 BSL_SAL_Free(pubKey);
299 }
300
IsELGAMALSetParaVaild(const CRYPT_ELGAMAL_Ctx * ctx,const CRYPT_ELGAMAL_Para * para)301 static int32_t IsELGAMALSetParaVaild(const CRYPT_ELGAMAL_Ctx *ctx, const CRYPT_ELGAMAL_Para *para)
302 {
303 if (ctx == NULL || para == NULL || para->q == NULL) {
304 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
305 return CRYPT_NULL_INPUT;
306 }
307 if (para->bits > ELGAMAL_MAX_MODULUS_BITS || para->bits <= 0) {
308 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_KEY_BITS);
309 return CRYPT_ELGAMAL_ERR_KEY_BITS;
310 }
311 if (para->k_bits > ELGAMAL_MAX_MODULUS_BITS || para->k_bits <= 0) {
312 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_KEY_KBITS);
313 return CRYPT_ELGAMAL_ERR_KEY_KBITS;
314 }
315 if (para->bits <= para->k_bits) {
316 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_KEY_BITS_KBITS);
317 return CRYPT_ELGAMAL_ERR_KEY_BITS_KBITS;
318 }
319 return CRYPT_SUCCESS;
320 }
321
CRYPT_ElGamal_DupPara(const CRYPT_ELGAMAL_Para * para)322 CRYPT_ELGAMAL_Para *CRYPT_ElGamal_DupPara(const CRYPT_ELGAMAL_Para *para)
323 {
324 CRYPT_ELGAMAL_Para *paraCopy = BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_Para));
325 if (paraCopy == NULL) {
326 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
327 return NULL;
328 }
329
330 paraCopy->bits = para->bits;
331 paraCopy->k_bits = para->k_bits;
332 paraCopy->q = BN_Dup(para->q);
333 if (paraCopy->q == NULL) {
334 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
335 ELGAMAL_FREE_PARA(paraCopy);
336 return NULL;
337 }
338
339 return paraCopy;
340 }
341
CRYPT_ELGAMAL_SetPara(CRYPT_ELGAMAL_Ctx * ctx,const BSL_Param * param)342 int32_t CRYPT_ELGAMAL_SetPara(CRYPT_ELGAMAL_Ctx *ctx, const BSL_Param *param)
343 {
344 if (ctx == NULL) {
345 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
346 return CRYPT_NULL_INPUT;
347 }
348
349 CRYPT_ELGAMAL_Para *para = CRYPT_ELGAMAL_NewPara(param);
350 if (para == NULL) {
351 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
352 return CRYPT_MEM_ALLOC_FAIL;
353 }
354
355 int32_t ret = IsELGAMALSetParaVaild(ctx, para);
356 if (ret != CRYPT_SUCCESS) {
357 CRYPT_ELGAMAL_FreePara(para);
358 return ret;
359 }
360
361 ELGAMAL_FREE_PARA(ctx->para);
362 ELGAMAL_FREE_PUB_KEY(ctx->pubKey);
363 ELGAMAL_FREE_PRV_KEY(ctx->prvKey);
364 ctx->para = para;
365
366 return CRYPT_SUCCESS;
367 }
368
CRYPT_ELGAMAL_GetBits(const CRYPT_ELGAMAL_Ctx * ctx)369 uint32_t CRYPT_ELGAMAL_GetBits(const CRYPT_ELGAMAL_Ctx *ctx)
370 {
371 if (ctx == NULL) {
372 return 0;
373 }
374 if (ctx->para != NULL) {
375 return ctx->para->bits;
376 }
377 if (ctx->prvKey != NULL) {
378 return BN_Bits(ctx->prvKey->p);
379 }
380 if (ctx->pubKey != NULL) {
381 return BN_Bits(ctx->pubKey->p);
382 }
383 return 0;
384 }
385
CRYPT_ELGAMAL_GetKBits(const CRYPT_ELGAMAL_Ctx * ctx)386 uint32_t CRYPT_ELGAMAL_GetKBits(const CRYPT_ELGAMAL_Ctx *ctx)
387 {
388 if (ctx == NULL) {
389 return 0;
390 }
391 if (ctx->para != NULL) {
392 return ctx->para->k_bits;
393 }
394
395 return 0;
396 }
397
ElGamal_NewPrvKey(uint32_t bits)398 CRYPT_ELGAMAL_PrvKey *ElGamal_NewPrvKey(uint32_t bits)
399 {
400 CRYPT_ELGAMAL_PrvKey *prvKey = (CRYPT_ELGAMAL_PrvKey *)BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_PrvKey));
401 if (prvKey == NULL) {
402 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
403 return NULL;
404 }
405 prvKey->p = BN_Create(bits);
406 prvKey->g = BN_Create(bits);
407 prvKey->x = BN_Create(bits);
408
409 if (prvKey->p == NULL || prvKey->g == NULL || prvKey->x == NULL) {
410 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
411 ELGAMAL_FREE_PRV_KEY(prvKey);
412 }
413
414 return prvKey;
415 }
416
ElGamal_NewPubKey(uint32_t bits)417 CRYPT_ELGAMAL_PubKey *ElGamal_NewPubKey(uint32_t bits)
418 {
419 CRYPT_ELGAMAL_PubKey *pubKey = (CRYPT_ELGAMAL_PubKey *)BSL_SAL_Malloc(sizeof(CRYPT_ELGAMAL_PubKey));
420 if (pubKey == NULL) {
421 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
422 return NULL;
423 }
424 pubKey->p = BN_Create(bits);
425 pubKey->g = BN_Create(bits);
426 pubKey->y = BN_Create(bits);
427 pubKey->q = BN_Create(bits);
428 if (pubKey->p == NULL || pubKey->g == NULL || pubKey->y == NULL || pubKey->q == NULL) {
429 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
430 ELGAMAL_FREE_PUB_KEY(pubKey);
431 }
432
433 return pubKey;
434 }
435
ElGamal_GenP(void * libCtx,BN_BigNum * p,CRYPT_ELGAMAL_Para * para,BN_Optimizer * optimizer)436 static int32_t ElGamal_GenP(void *libCtx, BN_BigNum *p, CRYPT_ELGAMAL_Para *para, BN_Optimizer *optimizer)
437 {
438 uint32_t bits = para->bits;
439 uint32_t k_bits = para->k_bits;
440 BN_BigNum *k = BN_Create(bits - k_bits);
441 BN_BigNum *kq = BN_Create(bits);
442 int32_t ret = CRYPT_MEM_ALLOC_FAIL;
443 if (kq == NULL || k == NULL) {
444 BSL_ERR_PUSH_ERROR(ret);
445 goto EXIT;
446 }
447
448 ret = BN_GenPrime(para->q, NULL, k_bits, false, optimizer, NULL);
449 if (ret != CRYPT_SUCCESS) {
450 BSL_ERR_PUSH_ERROR(ret);
451 goto EXIT;
452 }
453
454 ret = BN_RandEx(libCtx, k, (bits - k_bits), 1, 0);
455 if (ret != CRYPT_SUCCESS) {
456 BSL_ERR_PUSH_ERROR(ret);
457 goto EXIT;
458 }
459
460 ret = BN_Mul(kq, k, para->q, optimizer);
461 if (ret != CRYPT_SUCCESS) {
462 BSL_ERR_PUSH_ERROR(ret);
463 goto EXIT;
464 }
465
466 ret = BN_AddLimb(p, kq, 1);
467 if (ret != CRYPT_SUCCESS) {
468 BSL_ERR_PUSH_ERROR(ret);
469 }
470 EXIT:
471 BN_Destroy(k);
472 BN_Destroy(kq);
473 return ret;
474 }
475
ElGamal_CalcPrvKey(void * libCtx,CRYPT_ELGAMAL_PrvKey * prvKey,CRYPT_ELGAMAL_Para * para,BN_Optimizer * optimizer)476 static int32_t ElGamal_CalcPrvKey(void *libCtx, CRYPT_ELGAMAL_PrvKey *prvKey, CRYPT_ELGAMAL_Para *para,
477 BN_Optimizer *optimizer)
478 {
479 int32_t ret = CRYPT_SUCCESS;
480 BN_BigNum *xTop = BN_Create(para->bits);
481 if (xTop == NULL) {
482 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
483 return CRYPT_MEM_ALLOC_FAIL;
484 }
485
486 ret = ElGamal_GenP(libCtx, prvKey->p, para, optimizer);
487 if (ret != CRYPT_SUCCESS) {
488 BSL_ERR_PUSH_ERROR(ret);
489 goto EXIT;
490 }
491
492 ret = OriginalRoot(libCtx, prvKey->g, prvKey->p, para->q, para->bits);
493 if (ret != CRYPT_SUCCESS) {
494 BSL_ERR_PUSH_ERROR(ret);
495 goto EXIT;
496 }
497
498 ret = BN_SubLimb(xTop, para->q, 1);
499 if (ret != CRYPT_SUCCESS) {
500 BSL_ERR_PUSH_ERROR(ret);
501 goto EXIT;
502 }
503
504 ret = BN_RandRangeEx(libCtx, prvKey->x, xTop);
505 if (ret != CRYPT_SUCCESS) {
506 BSL_ERR_PUSH_ERROR(ret);
507 }
508 EXIT:
509 BN_Destroy(xTop);
510 return ret;
511 }
512
ElGamal_CalcPubKey(CRYPT_ELGAMAL_PubKey * pubKey,CRYPT_ELGAMAL_PrvKey * prvKey,BN_Optimizer * optimizer)513 static int32_t ElGamal_CalcPubKey(CRYPT_ELGAMAL_PubKey *pubKey, CRYPT_ELGAMAL_PrvKey *prvKey, BN_Optimizer *optimizer)
514 {
515 int32_t ret = BN_Copy(pubKey->p, prvKey->p);
516 if (ret != CRYPT_SUCCESS) {
517 BSL_ERR_PUSH_ERROR(ret);
518 return ret;
519 }
520 ret = BN_Copy(pubKey->g, prvKey->g);
521 if (ret != CRYPT_SUCCESS) {
522 BSL_ERR_PUSH_ERROR(ret);
523 return ret;
524 }
525 ret = BN_ModExp(pubKey->y, pubKey->g, prvKey->x, pubKey->p, optimizer);
526 if (ret != CRYPT_SUCCESS) {
527 BSL_ERR_PUSH_ERROR(ret);
528 }
529 return ret;
530 }
531
CRYPT_ELGAMAL_Gen(CRYPT_ELGAMAL_Ctx * ctx)532 int32_t CRYPT_ELGAMAL_Gen(CRYPT_ELGAMAL_Ctx *ctx)
533 {
534 if (ctx == NULL || ctx->para == NULL) {
535 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
536 return CRYPT_NULL_INPUT;
537 }
538 int32_t ret = CRYPT_MEM_ALLOC_FAIL;
539 BN_Optimizer *optimizer = NULL;
540 CRYPT_ELGAMAL_Ctx *newCtx = CRYPT_ELGAMAL_NewCtx();
541 if (newCtx == NULL) {
542 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
543 return CRYPT_MEM_ALLOC_FAIL;
544 }
545
546 newCtx->para = CRYPT_ElGamal_DupPara(ctx->para);
547 if (newCtx->para == NULL) {
548 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
549 goto ERR;
550 }
551
552 newCtx->prvKey = ElGamal_NewPrvKey(newCtx->para->bits);
553 newCtx->pubKey = ElGamal_NewPubKey(newCtx->para->bits);
554 optimizer = BN_OptimizerCreate();
555 if (optimizer == NULL || newCtx->prvKey == NULL || newCtx->pubKey == NULL) {
556 ret = CRYPT_MEM_ALLOC_FAIL;
557 BSL_ERR_PUSH_ERROR(ret);
558 goto ERR;
559 }
560 BN_OptimizerSetLibCtx(ctx->libCtx, optimizer);
561 ret = ElGamal_GenP(ctx->libCtx, newCtx->prvKey->p, newCtx->para, optimizer);
562 if (ret != CRYPT_SUCCESS) {
563 BSL_ERR_PUSH_ERROR(ret);
564 goto ERR;
565 }
566
567 ret = ElGamal_CalcPrvKey(ctx->libCtx, newCtx->prvKey, newCtx->para, optimizer);
568 if (ret != CRYPT_SUCCESS) {
569 BSL_ERR_PUSH_ERROR(ret);
570 goto ERR;
571 }
572
573 ret = ElGamal_CalcPubKey(newCtx->pubKey, newCtx->prvKey, optimizer);
574 if (ret != CRYPT_SUCCESS) {
575 BSL_ERR_PUSH_ERROR(ret);
576 goto ERR;
577 }
578 ELGAMAL_FREE_PARA(ctx->para);
579 ELGAMAL_FREE_PRV_KEY(ctx->prvKey);
580 ELGAMAL_FREE_PUB_KEY(ctx->pubKey);
581 BSL_SAL_ReferencesFree(&(newCtx->references));
582
583 ctx->prvKey = newCtx->prvKey;
584 ctx->pubKey = newCtx->pubKey;
585 ctx->para = newCtx->para;
586 BSL_SAL_FREE(newCtx);
587 BN_OptimizerDestroy(optimizer);
588
589 return ret;
590
591 ERR:
592 CRYPT_ELGAMAL_FreeCtx(newCtx);
593 BN_OptimizerDestroy(optimizer);
594 return ret;
595 }
596 #endif // HITLS_CRYPTO_ELGAMAL