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