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_utils.h"
20 #include "crypt_elgamal.h"
21 #include "elgamal_local.h"
22 #include "crypt_errno.h"
23 #include "bsl_sal.h"
24 #include "securec.h"
25 #include "bsl_err_internal.h"
26
AddZero(uint32_t bits,uint8_t * out,uint32_t * outLen)27 static int32_t AddZero(uint32_t bits, uint8_t *out, uint32_t *outLen)
28 {
29 int32_t ret;
30 uint32_t i;
31 uint32_t zeros = 0;
32 /* Divide bits by 8 to obtain the byte length. If it is smaller than the key length, pad it with 0. */
33 if ((*outLen) < BN_BITS_TO_BYTES(bits)) {
34 /* Divide bits by 8 to obtain the byte length. If it is smaller than the key length, pad it with 0. */
35 zeros = BN_BITS_TO_BYTES(bits) - (*outLen);
36 ret = memmove_s(out + zeros, BN_BITS_TO_BYTES(bits) - zeros, out, (*outLen));
37 if (ret != EOK) {
38 BSL_ERR_PUSH_ERROR(CRYPT_SECUREC_FAIL);
39 return CRYPT_SECUREC_FAIL;
40 }
41 for (i = 0; i < zeros; i++) {
42 out[i] = 0x0;
43 }
44 }
45 *outLen = BN_BITS_TO_BYTES(bits);
46 return CRYPT_SUCCESS;
47 }
48
ResultToOut(uint32_t bits,const BN_BigNum * result,uint8_t * out,uint32_t * outLen)49 static int32_t ResultToOut(uint32_t bits, const BN_BigNum *result, uint8_t *out, uint32_t *outLen)
50 {
51 int32_t ret = BN_Bn2Bin(result, out, outLen);
52 if (ret != CRYPT_SUCCESS) {
53 BSL_ERR_PUSH_ERROR(ret);
54 return ret;
55 }
56 return AddZero(bits, out, outLen);
57 }
58
CRYPT_ELGAMAL_PubEnc(const CRYPT_ELGAMAL_Ctx * ctx,const uint8_t * input,uint32_t inputLen,uint8_t * out1,uint32_t * out1Len,uint8_t * out2,uint32_t * out2Len)59 int32_t CRYPT_ELGAMAL_PubEnc(const CRYPT_ELGAMAL_Ctx *ctx, const uint8_t *input, uint32_t inputLen, uint8_t *out1,
60 uint32_t *out1Len, uint8_t *out2, uint32_t *out2Len)
61 {
62 int32_t ret;
63 CRYPT_ELGAMAL_PubKey *pubKey = ctx->pubKey;
64 if (pubKey == NULL) {
65 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
66 return CRYPT_NULL_INPUT;
67 }
68
69 BN_Mont *mont = BN_MontCreate(pubKey->p);
70
71 uint32_t bits = CRYPT_ELGAMAL_GetBits(ctx);
72 uint32_t k_bits = CRYPT_ELGAMAL_GetKBits(ctx);
73 BN_Optimizer *optimizer = BN_OptimizerCreate();
74 if (optimizer == NULL || mont == NULL) {
75 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
76 BN_MontDestroy(mont);
77 BN_OptimizerDestroy(optimizer);
78 return CRYPT_MEM_ALLOC_FAIL;
79 }
80
81 BN_BigNum *m = BN_Create(bits);
82 BN_BigNum *r = BN_Create(k_bits);
83 BN_BigNum *yr = BN_Create(bits);
84 BN_BigNum *c1 = BN_Create(bits);
85 BN_BigNum *c2 = BN_Create(bits);
86 BN_BigNum *gcd_result = BN_Create(bits);
87 BN_BigNum *top = BN_Create(k_bits);
88
89 bool createFailed =
90 (m == NULL || r == NULL || yr == NULL || c1 == NULL || c2 == NULL || gcd_result == NULL || top == NULL);
91 if (createFailed) {
92 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
93 ret = CRYPT_MEM_ALLOC_FAIL;
94 goto EXIT;
95 }
96
97 ret = BN_Bin2Bn(m, input, inputLen);
98 if (ret != CRYPT_SUCCESS) {
99 BSL_ERR_PUSH_ERROR(ret);
100 goto EXIT;
101 }
102
103 if (BN_IsNegative(m)) {
104 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_INPUT_VALUE);
105 ret = CRYPT_ELGAMAL_ERR_INPUT_VALUE;
106 goto EXIT;
107 }
108
109 ret = BN_SubLimb(top, pubKey->q, 1);
110 if (ret != CRYPT_SUCCESS) {
111 BSL_ERR_PUSH_ERROR(ret);
112 goto EXIT;
113 }
114
115 while (true) {
116 ret = BN_RandRangeEx(ctx->libCtx, r, top);
117 if (ret != CRYPT_SUCCESS) {
118 BSL_ERR_PUSH_ERROR(ret);
119 goto EXIT;
120 }
121 // Check whether r is relatively prime to p-1, if not, regenerate r
122 ret = BN_Gcd(gcd_result, r, top, optimizer);
123 if (ret != CRYPT_SUCCESS) {
124 BSL_ERR_PUSH_ERROR(ret);
125 goto EXIT;
126 }
127 if (BN_IsOne(gcd_result)) {
128 break;
129 }
130 }
131
132 ret = BN_MontExp(c1, pubKey->g, r, mont, optimizer);
133 if (ret != CRYPT_SUCCESS) {
134 BSL_ERR_PUSH_ERROR(ret);
135 goto EXIT;
136 }
137
138 ret = BN_MontExp(yr, pubKey->y, r, mont, optimizer);
139 if (ret != CRYPT_SUCCESS) {
140 BSL_ERR_PUSH_ERROR(ret);
141 goto EXIT;
142 }
143
144 ret = BN_ModMul(c2, m, yr, pubKey->p, optimizer);
145 if (ret != CRYPT_SUCCESS) {
146 BSL_ERR_PUSH_ERROR(ret);
147 goto EXIT;
148 }
149
150 ret = BN_Bn2Bin(c1, out1, out1Len);
151 if (ret != CRYPT_SUCCESS) {
152 BSL_ERR_PUSH_ERROR(ret);
153 goto EXIT;
154 }
155
156 ret = BN_Bn2Bin(c2, out2, out2Len);
157 if (ret != CRYPT_SUCCESS) {
158 BSL_ERR_PUSH_ERROR(ret);
159 }
160 EXIT:
161 BN_Destroy(m);
162 BN_Destroy(r);
163 BN_Destroy(yr);
164 BN_Destroy(c1);
165 BN_Destroy(c2);
166 BN_Destroy(gcd_result);
167 BN_Destroy(top);
168 BN_OptimizerDestroy(optimizer);
169 BN_MontDestroy(mont);
170 return ret;
171 }
172
CRYPT_ELGAMAL_PrvDec(const CRYPT_ELGAMAL_Ctx * ctx,const BN_BigNum * c1,const BN_BigNum * c2,uint32_t bits,uint8_t * out,uint32_t * outLen)173 int32_t CRYPT_ELGAMAL_PrvDec(const CRYPT_ELGAMAL_Ctx *ctx, const BN_BigNum *c1, const BN_BigNum *c2, uint32_t bits,
174 uint8_t *out, uint32_t *outLen)
175 {
176 int32_t ret;
177 CRYPT_ELGAMAL_PrvKey *prvKey = ctx->prvKey;
178 if (prvKey == NULL) {
179 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
180 return CRYPT_NULL_INPUT;
181 }
182
183 BN_Optimizer *optimizer = BN_OptimizerCreate();
184 if (optimizer == NULL) {
185 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
186 return CRYPT_MEM_ALLOC_FAIL;
187 }
188
189 bits = CRYPT_ELGAMAL_GetBits(ctx);
190 BN_BigNum *m = BN_Create(bits);
191 BN_BigNum *c1_x = BN_Create(bits);
192 BN_BigNum *c1_x_inv = BN_Create(bits);
193 BN_BigNum *result = BN_Create(bits);
194
195 bool createFailed = (m == NULL || c1_x == NULL || c1_x_inv == NULL || result == NULL);
196
197 if (createFailed) {
198 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
199 ret = CRYPT_MEM_ALLOC_FAIL;
200 goto EXIT;
201 }
202
203 ret = BN_ModExp(c1_x, c1, prvKey->x, prvKey->p, optimizer);
204 if (ret != CRYPT_SUCCESS) {
205 BSL_ERR_PUSH_ERROR(ret);
206 goto EXIT;
207 }
208
209 ret = BN_ModInv(c1_x_inv, c1_x, prvKey->p, optimizer);
210 if (ret != CRYPT_SUCCESS) {
211 BSL_ERR_PUSH_ERROR(ret);
212 goto EXIT;
213 }
214
215 ret = BN_ModMul(m, c2, c1_x_inv, prvKey->p, optimizer);
216 if (ret != CRYPT_SUCCESS) {
217 BSL_ERR_PUSH_ERROR(ret);
218 goto EXIT;
219 }
220
221 ret = ResultToOut(bits, result, out, outLen);
222 if (ret != CRYPT_SUCCESS) {
223 BSL_ERR_PUSH_ERROR(ret);
224 }
225 EXIT:
226 BN_Destroy(m);
227 BN_Destroy(c1_x);
228 BN_Destroy(c1_x_inv);
229 BN_Destroy(result);
230 BN_OptimizerDestroy(optimizer);
231 return ret;
232 }
233
EncryptInputCheck(const CRYPT_ELGAMAL_Ctx * ctx,const uint8_t * input,uint32_t inputLen,uint8_t * out,uint32_t * outLen)234 static int32_t EncryptInputCheck(const CRYPT_ELGAMAL_Ctx *ctx, const uint8_t *input, uint32_t inputLen, uint8_t *out,
235 uint32_t *outLen)
236 {
237 if (ctx == NULL || (input == NULL && inputLen != 0) || out == NULL || outLen == 0) {
238 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
239 return CRYPT_NULL_INPUT;
240 }
241
242 if (ctx->pubKey == NULL) {
243 // Check whether the public key information exists.
244 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_NO_KEY_INFO);
245 return CRYPT_ELGAMAL_NO_KEY_INFO;
246 }
247 // Check whether the length of the out is sufficient to place the encryption information.
248 uint32_t bits = CRYPT_ELGAMAL_GetBits(ctx);
249 if ((*outLen) < BN_BITS_TO_BYTES(bits)) {
250 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_BUFF_LEN_NOT_ENOUGH);
251 return CRYPT_ELGAMAL_BUFF_LEN_NOT_ENOUGH;
252 }
253 if (inputLen > BN_BITS_TO_BYTES(bits)) {
254 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_ENC_BITS);
255 return CRYPT_ELGAMAL_ERR_ENC_BITS;
256 }
257
258 return CRYPT_SUCCESS;
259 }
260
CRYPT_ELGAMAL_Encrypt(CRYPT_ELGAMAL_Ctx * ctx,const uint8_t * data,uint32_t dataLen,uint8_t * out,uint32_t * outLen)261 int32_t CRYPT_ELGAMAL_Encrypt(CRYPT_ELGAMAL_Ctx *ctx, const uint8_t *data, uint32_t dataLen, uint8_t *out,
262 uint32_t *outLen)
263 {
264 int32_t ret = EncryptInputCheck(ctx, data, dataLen, out, outLen);
265 if (ret != CRYPT_SUCCESS) {
266 BSL_ERR_PUSH_ERROR(ret);
267 return ret;
268 }
269
270 uint32_t bits = CRYPT_ELGAMAL_GetBits(ctx);
271 uint32_t out1Len = bits;
272 uint32_t out2Len = (*outLen) - bits;
273 uint32_t out3Len = 2 * bits ;
274 uint8_t *out1 = BSL_SAL_Calloc(1u, out1Len);
275 uint8_t *out2 = BSL_SAL_Calloc(1u, out2Len);
276 uint8_t *out3 = BSL_SAL_Calloc(1u, out3Len);
277 BN_BigNum *result = BN_Create(*outLen);
278 BN_BigNum *c = BN_Create(*outLen);
279 if (out1 == NULL || out2 == NULL || out3 == NULL || result == NULL || c == NULL) {
280 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
281 ret = CRYPT_MEM_ALLOC_FAIL;
282 goto EXIT;
283 }
284
285 ret = CRYPT_ELGAMAL_PubEnc(ctx, data, dataLen, out1, &out1Len, out2, &out2Len);
286 if (ret != CRYPT_SUCCESS) {
287 BSL_ERR_PUSH_ERROR(ret);
288 goto EXIT;
289 }
290
291 (void)memcpy_s(out3, out3Len, out1, out1Len); // c1
292 (void)memcpy_s(out3 + out1Len, out3Len - out1Len, out2, out2Len); // c2
293
294 ret = BN_Bin2Bn(c,out3,out3Len);
295 if (ret != CRYPT_SUCCESS) {
296 BSL_ERR_PUSH_ERROR(ret);
297 goto EXIT;
298 }
299
300 ret = ResultToOut(2 * bits, result, out, outLen);
301 if (ret != CRYPT_SUCCESS) {
302 BSL_ERR_PUSH_ERROR(ret);
303 }
304
305 EXIT:
306 BSL_SAL_FREE(out1);
307 BSL_SAL_FREE(out2);
308 BSL_SAL_FREE(out3);
309 BN_Destroy(result);
310 BN_Destroy(c);
311 return ret;
312 }
313
DecryptInputCheck(const CRYPT_ELGAMAL_Ctx * ctx,const uint8_t * data,uint32_t dataLen,const uint8_t * out,const uint32_t * outLen)314 static int32_t DecryptInputCheck(const CRYPT_ELGAMAL_Ctx *ctx, const uint8_t *data, uint32_t dataLen,
315 const uint8_t *out, const uint32_t *outLen)
316 {
317 if (ctx == NULL || data == NULL || out == NULL || outLen == NULL) {
318 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
319 return CRYPT_NULL_INPUT;
320 }
321
322 if (ctx->prvKey == NULL) {
323 // Check whether the private key information exists.
324 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_NO_KEY_INFO);
325 return CRYPT_ELGAMAL_NO_KEY_INFO;
326 }
327 // Check whether the length of the out is sufficient to place the decryption information.
328 uint32_t bits = CRYPT_ELGAMAL_GetBits(ctx);
329 if ((*outLen) < BN_BITS_TO_BYTES(bits)) {
330 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_BUFF_LEN_NOT_ENOUGH);
331 return CRYPT_ELGAMAL_BUFF_LEN_NOT_ENOUGH;
332 }
333 if (dataLen != 2 * BN_BITS_TO_BYTES(bits)) {
334 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_DEC_BITS);
335 return CRYPT_ELGAMAL_ERR_DEC_BITS;
336 }
337
338 return CRYPT_SUCCESS;
339 }
340
CheckCiphertext(const BN_BigNum * c1,const BN_BigNum * c2,const CRYPT_ELGAMAL_PrvKey * prvKey)341 static int32_t CheckCiphertext(const BN_BigNum *c1, const BN_BigNum *c2, const CRYPT_ELGAMAL_PrvKey *prvKey)
342 {
343 if (BN_Cmp(c1, prvKey->p) >= 0 || BN_IsNegative(c1)) {
344 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_INPUT_VALUE);
345 return CRYPT_ELGAMAL_ERR_INPUT_VALUE;
346 }
347 if (BN_Cmp(c2, prvKey->p) >= 0 || BN_IsNegative(c2)) {
348 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_INPUT_VALUE);
349 return CRYPT_ELGAMAL_ERR_INPUT_VALUE;
350 }
351 int32_t ret = CRYPT_SUCCESS;
352 BN_BigNum *gcd_result = BN_Create(BN_Bits(c1));
353 BN_Optimizer *optimizer = BN_OptimizerCreate();
354 if (gcd_result == NULL || optimizer == NULL) {
355 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
356 ret = CRYPT_MEM_ALLOC_FAIL;
357 goto EXIT;
358 }
359 ret = BN_Gcd(gcd_result, c1, prvKey->p, optimizer);
360 if (ret != CRYPT_SUCCESS) {
361 BSL_ERR_PUSH_ERROR(ret);
362 goto EXIT;
363 }
364 if (BN_IsOne(gcd_result) == false) {
365 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_INPUT_VALUE);
366 ret = CRYPT_ELGAMAL_ERR_INPUT_VALUE;
367 goto EXIT;
368 }
369 ret = BN_Gcd(gcd_result, c2, prvKey->p, optimizer);
370 if (ret != CRYPT_SUCCESS) {
371 BSL_ERR_PUSH_ERROR(ret);
372 goto EXIT;
373 }
374 if (BN_IsOne(gcd_result) == false) {
375 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_INPUT_VALUE);
376 ret = CRYPT_ELGAMAL_ERR_INPUT_VALUE;
377 }
378 EXIT:
379 BN_Destroy(gcd_result);
380 BN_OptimizerDestroy(optimizer);
381 return ret;
382 }
383
CRYPT_ELGAMAL_Decrypt(CRYPT_ELGAMAL_Ctx * ctx,const uint8_t * data,uint32_t dataLen,uint8_t * out,uint32_t * outLen)384 int32_t CRYPT_ELGAMAL_Decrypt(CRYPT_ELGAMAL_Ctx *ctx, const uint8_t *data, uint32_t dataLen, uint8_t *out,
385 uint32_t *outLen)
386 {
387 int32_t ret = DecryptInputCheck(ctx, data, dataLen, out, outLen);
388 if (ret != CRYPT_SUCCESS) {
389 BSL_ERR_PUSH_ERROR(ret);
390 return ret;
391 }
392
393 uint32_t bits = CRYPT_ELGAMAL_GetBits(ctx);
394 uint32_t data1Len = BN_BITS_TO_BYTES(bits);
395 uint32_t data2Len = dataLen - BN_BITS_TO_BYTES(bits);
396 uint8_t *data1 = BSL_SAL_Calloc(1u, data1Len);
397 uint8_t *data2 = BSL_SAL_Calloc(1u, data2Len);
398 BN_BigNum *c1 = BN_Create(bits);
399 BN_BigNum *c2 = BN_Create(bits);
400
401 if (data1 == NULL || data2 == NULL || c1 == NULL || c2 == NULL) {
402 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
403 ret = CRYPT_MEM_ALLOC_FAIL;
404 goto EXIT;
405 }
406
407 (void)memcpy_s(data1, data1Len, data, data1Len); // c1
408 (void)memcpy_s(data2, data2Len, data + data1Len, data2Len); // c2
409
410 ret = BN_Bin2Bn(c1, data1, data1Len);
411 if (ret != CRYPT_SUCCESS) {
412 BSL_ERR_PUSH_ERROR(ret);
413 goto EXIT;
414 }
415
416 ret = BN_Bin2Bn(c2, data2, data2Len);
417 if (ret != CRYPT_SUCCESS) {
418 BSL_ERR_PUSH_ERROR(ret);
419 goto EXIT;
420 }
421
422 ret = CheckCiphertext(c1, c2, ctx->prvKey);
423 if (ret != CRYPT_SUCCESS) {
424 BSL_ERR_PUSH_ERROR(ret);
425 goto EXIT;
426 }
427
428 ret = CRYPT_ELGAMAL_PrvDec(ctx, c1, c2, bits, out, outLen);
429 if (ret != CRYPT_SUCCESS) {
430 BSL_ERR_PUSH_ERROR(ret);
431 }
432 EXIT:
433 BSL_SAL_FREE(data1);
434 BSL_SAL_FREE(data2);
435 BN_Destroy(c1);
436 BN_Destroy(c2);
437 return ret;
438 }
439
CRYPT_ELGAMAL_GetLen(const CRYPT_ELGAMAL_Ctx * ctx,GetLenFunc func,void * val,uint32_t len)440 static uint32_t CRYPT_ELGAMAL_GetLen(const CRYPT_ELGAMAL_Ctx *ctx, GetLenFunc func, void *val, uint32_t len)
441 {
442 if (val == NULL || len != sizeof(int32_t)) {
443 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
444 return CRYPT_NULL_INPUT;
445 }
446
447 *(int32_t *)val = func(ctx);
448 return CRYPT_SUCCESS;
449 }
450
CRYPT_ELGAMAL_Ctrl(CRYPT_ELGAMAL_Ctx * ctx,int32_t opt,void * val,uint32_t len)451 int32_t CRYPT_ELGAMAL_Ctrl(CRYPT_ELGAMAL_Ctx *ctx, int32_t opt, void *val, uint32_t len)
452 {
453 if (ctx == NULL) {
454 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
455 return CRYPT_NULL_INPUT;
456 }
457 switch (opt) {
458 case CRYPT_CTRL_GET_BITS:
459 return CRYPT_ELGAMAL_GetLen(ctx, (GetLenFunc)CRYPT_ELGAMAL_GetBits, val, len);
460 case CRYPT_CTRL_GET_SECBITS:
461 return CRYPT_ELGAMAL_GetLen(ctx, (GetLenFunc)CRYPT_ELGAMAL_GetSecBits, val, len);
462 default:
463 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_CTRL_NOT_SUPPORT_ERROR);
464 return CRYPT_ELGAMAL_CTRL_NOT_SUPPORT_ERROR;
465 }
466 }
467
468 #endif // HITLS_CRYPTO_ELGAMAL