• 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_PAILLIER
18 
19 #include "crypt_utils.h"
20 #include "crypt_paillier.h"
21 #include "paillier_local.h"
22 #include "crypt_errno.h"
23 #include "bsl_sal.h"
24 #include "securec.h"
25 #include "bsl_err_internal.h"
26 
CRYPT_PAILLIER_PubEnc(const CRYPT_PAILLIER_Ctx * ctx,const uint8_t * input,uint32_t inputLen,uint8_t * out,uint32_t * outLen)27 int32_t  CRYPT_PAILLIER_PubEnc(const CRYPT_PAILLIER_Ctx *ctx, const uint8_t *input, uint32_t inputLen,
28     uint8_t *out, uint32_t *outLen)
29 {
30     int32_t ret;
31     CRYPT_PAILLIER_PubKey *pubKey = ctx->pubKey;
32     if (pubKey == NULL) {
33         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
34         return CRYPT_NULL_INPUT;
35     }
36 
37     uint32_t bits = CRYPT_PAILLIER_GetBits(ctx);
38     BN_Optimizer *optimizer = BN_OptimizerCreate();
39     if (optimizer == NULL) {
40         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
41         return CRYPT_MEM_ALLOC_FAIL;
42     }
43 
44     BN_BigNum *m = BN_Create(bits);
45     BN_BigNum *r = BN_Create(bits);
46 
47     BN_BigNum *gm = BN_Create(bits);
48     BN_BigNum *rn = BN_Create(bits);
49 
50     BN_BigNum *result = BN_Create(bits);
51     BN_BigNum *gcd_result = BN_Create(bits);
52 
53     bool createFailed = (m == NULL || r == NULL || gm == NULL || rn == NULL || result == NULL || gcd_result == NULL);
54     if (createFailed) {
55         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
56         ret = CRYPT_MEM_ALLOC_FAIL;
57         goto EXIT;
58     }
59 
60     ret = BN_Bin2Bn(m, input, inputLen);
61     if (ret != CRYPT_SUCCESS) {
62         BSL_ERR_PUSH_ERROR(ret);
63         goto EXIT;
64     }
65 
66     // Check whether m is less than n and non-negative
67     if (BN_Cmp(m, pubKey->n) >= 0 || BN_IsNegative(m)) {
68         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_INPUT_VALUE);
69         ret = CRYPT_PAILLIER_ERR_INPUT_VALUE;
70         goto EXIT;
71     }
72 
73     ret = BN_RandRangeEx(ctx->libCtx, r, pubKey->n);
74     if (ret != CRYPT_SUCCESS) {
75         BSL_ERR_PUSH_ERROR(ret);
76         goto EXIT;
77     }
78 
79     while (true) {
80         // Check whether r is relatively prime to n, if not, regenerate r
81         ret = BN_Gcd(gcd_result, r, pubKey->n, optimizer);
82         if (ret != CRYPT_SUCCESS) {
83             BSL_ERR_PUSH_ERROR(ret);
84             goto EXIT;
85         }
86         if (BN_IsOne(gcd_result)) {
87             break;
88         }
89         ret = BN_RandRangeEx(ctx->libCtx, r, pubKey->n);
90         if (ret != CRYPT_SUCCESS) {
91             BSL_ERR_PUSH_ERROR(ret);
92             goto EXIT;
93         }
94     }
95 
96     ret = BN_ModExp(gm, pubKey->g, m, pubKey->n2, optimizer);
97     if (ret != CRYPT_SUCCESS) {
98         BSL_ERR_PUSH_ERROR(ret);
99         goto EXIT;
100     }
101 
102     ret = BN_ModExp(rn, r, pubKey->n, pubKey->n2, optimizer);
103     if (ret != CRYPT_SUCCESS) {
104         BSL_ERR_PUSH_ERROR(ret);
105         goto EXIT;
106     }
107 
108     ret = BN_ModMul(result, gm, rn, pubKey->n2, optimizer);
109     if (ret != CRYPT_SUCCESS) {
110         BSL_ERR_PUSH_ERROR(ret);
111         goto EXIT;
112     }
113 
114     ret = BN_Bn2Bin(result, out, outLen);
115     if (ret != CRYPT_SUCCESS) {
116         BSL_ERR_PUSH_ERROR(ret);
117     }
118 EXIT:
119     BN_Destroy(m);
120     BN_Destroy(r);
121     BN_Destroy(gm);
122     BN_Destroy(rn);
123     BN_Destroy(result);
124     BN_Destroy(gcd_result);
125     BN_OptimizerDestroy(optimizer);
126     return ret;
127 }
128 
CRYPT_PAILLIER_PrvDec(const CRYPT_PAILLIER_Ctx * ctx,const BN_BigNum * ciphertext,uint32_t bits,uint8_t * out,uint32_t * outLen)129 int32_t CRYPT_PAILLIER_PrvDec(const CRYPT_PAILLIER_Ctx *ctx, const BN_BigNum *ciphertext, uint32_t bits,
130     uint8_t *out, uint32_t *outLen)
131 {
132     int32_t ret;
133     CRYPT_PAILLIER_PrvKey *prvKey = ctx->prvKey;
134     if (prvKey == NULL) {
135         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
136         return CRYPT_NULL_INPUT;
137     }
138 
139     BN_Optimizer *optimizer = BN_OptimizerCreate();
140     if (optimizer == NULL) {
141         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
142         return CRYPT_MEM_ALLOC_FAIL;
143     }
144 
145     BN_BigNum *m = BN_Create(bits);
146     BN_BigNum *result = BN_Create(bits);
147 
148     bool createFailed = (m == NULL || result == NULL);
149 
150     if (createFailed) {
151         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
152         ret = CRYPT_MEM_ALLOC_FAIL;
153         goto EXIT;
154     }
155 
156     ret = BN_ModExp(m, ciphertext, prvKey->lambda, prvKey->n2, optimizer);
157     if (ret != CRYPT_SUCCESS) {
158         BSL_ERR_PUSH_ERROR(ret);
159         goto EXIT;
160     }
161 
162     ret = BN_SubLimb(result, m, 1);
163     if (ret != CRYPT_SUCCESS) {
164         BSL_ERR_PUSH_ERROR(ret);
165         goto EXIT;
166     }
167 
168     ret = BN_Div(result, NULL, result, prvKey->n, optimizer);
169     if (ret != CRYPT_SUCCESS) {
170         BSL_ERR_PUSH_ERROR(ret);
171         goto EXIT;
172     }
173 
174     ret = BN_ModMul(result, result, prvKey->mu, prvKey->n, optimizer);
175     if (ret != CRYPT_SUCCESS) {
176         BSL_ERR_PUSH_ERROR(ret);
177         goto EXIT;
178     }
179 
180     ret = BN_Bn2Bin(result, out, outLen);
181     if (ret != CRYPT_SUCCESS) {
182         BSL_ERR_PUSH_ERROR(ret);
183     }
184 EXIT:
185     BN_Destroy(m);
186     BN_Destroy(result);
187     BN_OptimizerDestroy(optimizer);
188     return ret;
189 }
190 
EncryptInputCheck(const CRYPT_PAILLIER_Ctx * ctx,const uint8_t * input,uint32_t inputLen,const uint8_t * out,const uint32_t * outLen)191 static int32_t EncryptInputCheck(const CRYPT_PAILLIER_Ctx *ctx, const uint8_t *input, uint32_t inputLen,
192     const uint8_t *out, const uint32_t *outLen)
193 {
194     if (ctx == NULL || (input == NULL && inputLen != 0) || out == NULL || outLen == 0) {
195         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
196         return CRYPT_NULL_INPUT;
197     }
198 
199     if (ctx->pubKey == NULL) {
200         // Check whether the public key information exists.
201         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_NO_KEY_INFO);
202         return CRYPT_PAILLIER_NO_KEY_INFO;
203     }
204     // Check whether the length of the out is sufficient to place the encryption information.
205     uint32_t bits = CRYPT_PAILLIER_GetBits(ctx);
206     if ((*outLen) < BN_BITS_TO_BYTES(bits)) {
207         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_BUFF_LEN_NOT_ENOUGH);
208         return CRYPT_PAILLIER_BUFF_LEN_NOT_ENOUGH;
209     }
210     if (inputLen > BN_BITS_TO_BYTES(bits)) {
211         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_ENC_BITS);
212         return CRYPT_PAILLIER_ERR_ENC_BITS;
213     }
214 
215     return CRYPT_SUCCESS;
216 }
217 
CRYPT_PAILLIER_Encrypt(CRYPT_PAILLIER_Ctx * ctx,const uint8_t * data,uint32_t dataLen,uint8_t * out,uint32_t * outLen)218 int32_t CRYPT_PAILLIER_Encrypt(CRYPT_PAILLIER_Ctx *ctx, const uint8_t *data, uint32_t dataLen,
219     uint8_t *out, uint32_t *outLen)
220 {
221     int32_t ret = EncryptInputCheck(ctx, data, dataLen, out, outLen);
222     if (ret != CRYPT_SUCCESS) {
223         return ret;
224     }
225     ret = CRYPT_PAILLIER_PubEnc(ctx, data, dataLen, out, outLen);
226     if (ret != CRYPT_SUCCESS) {
227         BSL_ERR_PUSH_ERROR(ret);
228     }
229     return ret;
230 }
231 
DecryptInputCheck(const CRYPT_PAILLIER_Ctx * ctx,const uint8_t * data,uint32_t dataLen,const uint8_t * out,const uint32_t * outLen)232 static int32_t DecryptInputCheck(const CRYPT_PAILLIER_Ctx *ctx, const uint8_t *data, uint32_t dataLen,
233     const uint8_t *out, const uint32_t *outLen)
234 {
235     if (ctx == NULL || data == NULL || out == NULL || outLen == NULL) {
236         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
237         return CRYPT_NULL_INPUT;
238     }
239 
240     if (ctx->prvKey == NULL) {
241         // Check whether the private key information exists.
242         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_NO_KEY_INFO);
243         return CRYPT_PAILLIER_NO_KEY_INFO;
244     }
245     // Check whether the length of the out is sufficient to place the decryption information.
246     uint32_t bits = CRYPT_PAILLIER_GetBits(ctx);
247     if ((*outLen) < BN_BITS_TO_BYTES(bits)) {
248         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_BUFF_LEN_NOT_ENOUGH);
249         return CRYPT_PAILLIER_BUFF_LEN_NOT_ENOUGH;
250     }
251     if (dataLen != BN_BITS_TO_BYTES(bits) * 2) {
252         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_DEC_BITS);
253         return CRYPT_PAILLIER_ERR_DEC_BITS;
254     }
255 
256     return CRYPT_SUCCESS;
257 }
258 
CRYPT_PAILLIER_CheckCiphertext(const BN_BigNum * ciphertext,const CRYPT_PAILLIER_PrvKey * prvKey)259 static int32_t CRYPT_PAILLIER_CheckCiphertext(const BN_BigNum* ciphertext, const CRYPT_PAILLIER_PrvKey* prvKey)
260 {
261     if (BN_Cmp(ciphertext, prvKey->n2) >= 0 || BN_IsNegative(ciphertext)) {
262         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_INPUT_VALUE);
263         return CRYPT_PAILLIER_ERR_INPUT_VALUE;
264     }
265     int32_t ret = CRYPT_SUCCESS;
266     BN_BigNum *gcd_result = BN_Create(BN_Bits(ciphertext));
267     BN_Optimizer *optimizer = BN_OptimizerCreate();
268     if (gcd_result == NULL || optimizer == NULL) {
269         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
270         ret = CRYPT_MEM_ALLOC_FAIL;
271         goto EXIT;
272     }
273     ret = BN_Gcd(gcd_result, ciphertext, prvKey->n2, optimizer);
274     if (ret != CRYPT_SUCCESS) {
275         BSL_ERR_PUSH_ERROR(ret);
276         goto EXIT;
277     }
278     if (BN_IsOne(gcd_result) == false) {
279         BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_INPUT_VALUE);
280         ret = CRYPT_PAILLIER_ERR_INPUT_VALUE;
281     }
282 EXIT:
283     BN_Destroy(gcd_result);
284     BN_OptimizerDestroy(optimizer);
285     return ret;
286 }
287 
CRYPT_PAILLIER_Decrypt(CRYPT_PAILLIER_Ctx * ctx,const uint8_t * data,uint32_t dataLen,uint8_t * out,uint32_t * outLen)288 int32_t CRYPT_PAILLIER_Decrypt(CRYPT_PAILLIER_Ctx *ctx, const uint8_t *data, uint32_t dataLen,
289     uint8_t *out, uint32_t *outLen)
290 {
291     int32_t ret = DecryptInputCheck(ctx, data, dataLen, out, outLen);
292     if (ret != CRYPT_SUCCESS) {
293         return ret;
294     }
295 
296     uint32_t bits = CRYPT_PAILLIER_GetBits(ctx);
297     BN_BigNum *c = BN_Create(bits);
298 
299     if (c == NULL) {
300         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
301         return CRYPT_MEM_ALLOC_FAIL;
302     }
303 
304     ret = BN_Bin2Bn(c, data, dataLen);
305     if (ret != CRYPT_SUCCESS) {
306         BSL_ERR_PUSH_ERROR(ret);
307         goto EXIT;
308     }
309 
310     // check whether c is in Zn2*
311     ret = CRYPT_PAILLIER_CheckCiphertext(c, ctx->prvKey);
312     if (ret != CRYPT_SUCCESS) {
313         BSL_ERR_PUSH_ERROR(ret);
314         goto EXIT;
315     }
316 
317     ret = CRYPT_PAILLIER_PrvDec(ctx, c, bits, out, outLen);
318     if (ret != CRYPT_SUCCESS) {
319         BSL_ERR_PUSH_ERROR(ret);
320     }
321 
322 EXIT:
323     BN_Destroy(c);
324     return ret;
325 }
326 
CRYPT_PAILLIER_GetLen(const CRYPT_PAILLIER_Ctx * ctx,GetLenFunc func,void * val,uint32_t len)327 static int32_t CRYPT_PAILLIER_GetLen(const CRYPT_PAILLIER_Ctx *ctx, GetLenFunc func, void *val, uint32_t len)
328 {
329     if (val == NULL || len != sizeof(int32_t)) {
330         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
331         return CRYPT_NULL_INPUT;
332     }
333 
334     *(int32_t *)val = func(ctx);
335     return CRYPT_SUCCESS;
336 }
337 
CRYPT_PAILLIER_Ctrl(CRYPT_PAILLIER_Ctx * ctx,int32_t opt,void * val,uint32_t len)338 int32_t CRYPT_PAILLIER_Ctrl(CRYPT_PAILLIER_Ctx *ctx, int32_t opt, void *val, uint32_t len)
339 {
340     if (ctx == NULL) {
341         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
342         return CRYPT_NULL_INPUT;
343     }
344     switch (opt) {
345         case CRYPT_CTRL_GET_BITS:
346             return CRYPT_PAILLIER_GetLen(ctx, (GetLenFunc)CRYPT_PAILLIER_GetBits, val, len);
347         case CRYPT_CTRL_GET_SECBITS:
348             return CRYPT_PAILLIER_GetLen(ctx, (GetLenFunc)CRYPT_PAILLIER_GetSecBits, val, len);
349         default:
350             BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_CTRL_NOT_SUPPORT_ERROR);
351             return CRYPT_PAILLIER_CTRL_NOT_SUPPORT_ERROR;
352     }
353 }
354 
355 #endif  // HITLS_CRYPTO_PAILLIER