• 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_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