• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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