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_types.h"
20 #include "crypt_paillier.h"
21 #include "crypt_utils.h"
22 #include "bsl_err_internal.h"
23 #include "paillier_local.h"
24 #include "crypt_errno.h"
25 #include "securec.h"
26 #include "bsl_sal.h"
27 #include "crypt_params_key.h"
28
29 typedef struct {
30 BSL_Param *n; /**< Paillier private key parameter marked as n */
31 BSL_Param *lambda; /**< Paillier private key parameter marked as lambda */
32 BSL_Param *mu; /**< Paillier private key parameter marked as mu */
33 BSL_Param *n2; /**< Paillier private key parameter marked as n2 */
34 } CRYPT_PaillierPrvParam;
35
36 typedef struct {
37 BSL_Param *n; /**< Paillier public key parameter marked as n */
38 BSL_Param *g; /**< Paillier public key parameter marked as g */
39 BSL_Param *n2; /**< Paillier public key parameter marked as n2 */
40 } CRYPT_PaillierPubParam;
41
42 #define PARAMISNULL(a) (a == NULL || a->value == NULL)
43
CheckSquare(const BN_BigNum * n2,const BN_BigNum * n,uint32_t bits)44 static int32_t CheckSquare(const BN_BigNum *n2, const BN_BigNum *n, uint32_t bits)
45 {
46 BN_BigNum *tmp = BN_Create(bits);
47 BN_Optimizer *optimizer = BN_OptimizerCreate();
48 int32_t ret;
49 if (optimizer == NULL || tmp == NULL) {
50 ret = CRYPT_MEM_ALLOC_FAIL;
51 BSL_ERR_PUSH_ERROR(ret);
52 goto EXIT;
53 }
54
55 ret = BN_Sqr(tmp, n, optimizer);
56 if (ret != CRYPT_SUCCESS) {
57 BSL_ERR_PUSH_ERROR(ret);
58 goto EXIT;
59 }
60
61 if (BN_Cmp(tmp, n2) != 0) {
62 BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_INPUT_VALUE);
63 ret = CRYPT_PAILLIER_ERR_INPUT_VALUE;
64 }
65
66 EXIT:
67 BN_Destroy(tmp);
68 BN_OptimizerDestroy(optimizer);
69 return ret;
70 }
71
SetPrvPara(const CRYPT_PAILLIER_PrvKey * prvKey,const CRYPT_PaillierPrvParam * prv)72 static int32_t SetPrvPara(const CRYPT_PAILLIER_PrvKey *prvKey, const CRYPT_PaillierPrvParam *prv)
73 {
74 int32_t ret = BN_Bin2Bn(prvKey->n, prv->n->value, prv->n->valueLen);
75 if (ret != CRYPT_SUCCESS) {
76 BSL_ERR_PUSH_ERROR(ret);
77 return ret;
78 }
79
80 uint32_t bnBits = BN_Bits(prvKey->n);
81 if (bnBits > PAILLIER_MAX_MODULUS_BITS || bnBits <= 0) {
82 BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_KEY_BITS);
83 return CRYPT_PAILLIER_ERR_KEY_BITS;
84 }
85
86 ret = BN_Bin2Bn(prvKey->lambda, prv->lambda->value, prv->lambda->valueLen);
87 if (ret != CRYPT_SUCCESS) {
88 BSL_ERR_PUSH_ERROR(ret);
89 return ret;
90 }
91 ret = BN_Bin2Bn(prvKey->mu, prv->mu->value, prv->mu->valueLen);
92 if (ret != CRYPT_SUCCESS) {
93 BSL_ERR_PUSH_ERROR(ret);
94 return ret;
95 }
96 ret = BN_Bin2Bn(prvKey->n2, prv->n2->value, prv->n2->valueLen);
97 if (ret != CRYPT_SUCCESS) {
98 BSL_ERR_PUSH_ERROR(ret);
99 return ret;
100 }
101 ret = CheckSquare(prvKey->n2, prvKey->n, prv->n2->valueLen * 8);
102 if (ret != CRYPT_SUCCESS) {
103 BSL_ERR_PUSH_ERROR(ret);
104 return ret;
105 }
106 if (BN_IsZero(prvKey->mu) || BN_IsOne(prvKey->mu)) {
107 BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_INPUT_VALUE);
108 return CRYPT_PAILLIER_ERR_INPUT_VALUE;
109 }
110 return ret;
111 }
112
SetPrvBasicCheck(const CRYPT_PAILLIER_Ctx * ctx,BSL_Param * para,CRYPT_PaillierPrvParam * prv)113 static int32_t SetPrvBasicCheck(const CRYPT_PAILLIER_Ctx *ctx, BSL_Param *para, CRYPT_PaillierPrvParam *prv)
114 {
115 if (ctx == NULL || para == NULL) {
116 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
117 return CRYPT_NULL_INPUT;
118 }
119 prv->n = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N);
120 prv->lambda = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_LAMBDA);
121 prv->mu = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_MU);
122 prv->n2 = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N2);
123 if (PARAMISNULL(prv->n) || PARAMISNULL(prv->lambda) || PARAMISNULL(prv->mu) || PARAMISNULL(prv->n2) ||
124 prv->lambda->valueLen == 0 || prv->mu->valueLen == 0 || prv->n->valueLen == 0 || prv->n2->valueLen == 0) {
125 BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_INPUT_VALUE);
126 return CRYPT_PAILLIER_ERR_INPUT_VALUE;
127 }
128 return CRYPT_SUCCESS;
129 }
130
CRYPT_PAILLIER_SetPrvKey(CRYPT_PAILLIER_Ctx * ctx,const BSL_Param * para)131 int32_t CRYPT_PAILLIER_SetPrvKey(CRYPT_PAILLIER_Ctx *ctx, const BSL_Param *para)
132 {
133 CRYPT_PaillierPrvParam prv = {0};
134 int32_t ret = SetPrvBasicCheck(ctx, (BSL_Param *)(uintptr_t)para, &prv);
135 if (ret != CRYPT_SUCCESS) {
136 return ret;
137 }
138 CRYPT_PAILLIER_Ctx *newCtx = CRYPT_PAILLIER_NewCtx();
139 if (newCtx == NULL) {
140 return CRYPT_MEM_ALLOC_FAIL;
141 }
142 // Bit length is obtained by multiplying byte length by 8.
143 newCtx->prvKey = Paillier_NewPrvKey(prv.lambda->valueLen * 8);
144 if (newCtx->prvKey == NULL) {
145 ret = CRYPT_MEM_ALLOC_FAIL;
146 BSL_ERR_PUSH_ERROR(ret);
147 goto ERR;
148 }
149
150 ret = SetPrvPara(newCtx->prvKey, &prv);
151 if (ret != CRYPT_SUCCESS) {
152 BSL_ERR_PUSH_ERROR(ret);
153 goto ERR;
154 }
155
156 PAILLIER_FREE_PRV_KEY(ctx->prvKey);
157 ctx->prvKey = newCtx->prvKey;
158
159 BSL_SAL_ReferencesFree(&(newCtx->references));
160 BSL_SAL_FREE(newCtx);
161 return ret;
162 ERR:
163 CRYPT_PAILLIER_FreeCtx(newCtx);
164 return ret;
165 }
166
SetPubBasicCheck(const CRYPT_PAILLIER_Ctx * ctx,BSL_Param * para,CRYPT_PaillierPubParam * pub)167 static int32_t SetPubBasicCheck(const CRYPT_PAILLIER_Ctx *ctx, BSL_Param *para, CRYPT_PaillierPubParam *pub)
168 {
169 if (ctx == NULL || para == NULL) {
170 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
171 return CRYPT_NULL_INPUT;
172 }
173 pub->n = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N);
174 pub->g = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_G);
175 pub->n2 = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N2);
176 if (PARAMISNULL(pub->n) || PARAMISNULL(pub->g) || PARAMISNULL(pub->n2)) {
177 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
178 return CRYPT_NULL_INPUT;
179 }
180 return CRYPT_SUCCESS;
181 }
182
CRYPT_PAILLIER_SetPubKey(CRYPT_PAILLIER_Ctx * ctx,const BSL_Param * para)183 int32_t CRYPT_PAILLIER_SetPubKey(CRYPT_PAILLIER_Ctx *ctx, const BSL_Param *para)
184 {
185 CRYPT_PaillierPubParam pub = {0};
186 int32_t ret = SetPubBasicCheck(ctx, (BSL_Param *)(uintptr_t)para, &pub);
187 if (ret != CRYPT_SUCCESS) {
188 BSL_ERR_PUSH_ERROR(ret);
189 return ret;
190 }
191 CRYPT_PAILLIER_PubKey *newPub = NULL;
192
193 /* Bit length is obtained by multiplying byte length by 8. */
194 newPub = Paillier_NewPubKey(pub.n->valueLen * 8);
195 if (newPub == NULL) {
196 return CRYPT_MEM_ALLOC_FAIL;
197 }
198 GOTO_ERR_IF(BN_Bin2Bn(newPub->n, pub.n->value, pub.n->valueLen), ret);
199 uint32_t bnBits = BN_Bits(newPub->n);
200 if (bnBits > PAILLIER_MAX_MODULUS_BITS || bnBits <= 0) {
201 ret = CRYPT_PAILLIER_ERR_KEY_BITS;
202 BSL_ERR_PUSH_ERROR(ret);
203 goto ERR;
204 }
205 GOTO_ERR_IF(BN_Bin2Bn(newPub->g, pub.g->value, pub.g->valueLen), ret);
206 GOTO_ERR_IF(BN_Bin2Bn(newPub->n2, pub.n2->value, pub.n2->valueLen), ret);
207
208 GOTO_ERR_IF(CheckSquare(newPub->n2, newPub->n, pub.n->valueLen * 8), ret);
209
210 PAILLIER_FREE_PUB_KEY(ctx->pubKey);
211 ctx->pubKey = newPub;
212 return ret;
213 ERR:
214 PAILLIER_FREE_PUB_KEY(newPub);
215 return ret;
216 }
217
GetPrvBasicCheck(const CRYPT_PAILLIER_Ctx * ctx,BSL_Param * para,CRYPT_PaillierPrvParam * prv)218 static int32_t GetPrvBasicCheck(const CRYPT_PAILLIER_Ctx *ctx, BSL_Param *para, CRYPT_PaillierPrvParam *prv)
219 {
220 if (ctx == NULL || ctx->prvKey == NULL || para == NULL) {
221 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
222 return CRYPT_NULL_INPUT;
223 }
224 prv->n = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N);
225 prv->lambda = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_LAMBDA);
226 prv->mu = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_MU);
227 prv->n2 = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N2);
228 if (PARAMISNULL(prv->lambda) || PARAMISNULL(prv->mu)) {
229 BSL_ERR_PUSH_ERROR(CRYPT_PAILLIER_ERR_INPUT_VALUE);
230 return CRYPT_PAILLIER_ERR_INPUT_VALUE;
231 }
232 return CRYPT_SUCCESS;
233 }
234
CRYPT_PAILLIER_GetPrvKey(const CRYPT_PAILLIER_Ctx * ctx,BSL_Param * para)235 int32_t CRYPT_PAILLIER_GetPrvKey(const CRYPT_PAILLIER_Ctx *ctx, BSL_Param *para)
236 {
237 CRYPT_PaillierPrvParam prv = {0};
238 int32_t ret = GetPrvBasicCheck(ctx, para, &prv);
239 if (ret != CRYPT_SUCCESS) {
240 return ret;
241 }
242
243 prv.lambda->useLen = prv.lambda->valueLen;
244 GOTO_ERR_IF(BN_Bn2Bin(ctx->prvKey->lambda, prv.lambda->value, &(prv.lambda->useLen)), ret);
245 prv.mu->useLen = prv.mu->valueLen;
246 GOTO_ERR_IF(BN_Bn2Bin(ctx->prvKey->mu, prv.mu->value, &(prv.mu->useLen)), ret);
247 if (!PARAMISNULL(prv.n)) {
248 prv.n->useLen = prv.n->valueLen;
249 GOTO_ERR_IF(BN_Bn2Bin(ctx->prvKey->n, prv.n->value, &(prv.n->useLen)), ret);
250 }
251 if (!PARAMISNULL(prv.n2)) {
252 prv.n2->useLen = prv.n2->valueLen;
253 GOTO_ERR_IF(BN_Bn2Bin(ctx->prvKey->n2, prv.n2->value, &(prv.n2->useLen)), ret);
254 }
255 return CRYPT_SUCCESS;
256 ERR:
257 if (!PARAMISNULL(prv.lambda) && prv.lambda->useLen != 0) {
258 BSL_SAL_CleanseData(prv.lambda->value, prv.lambda->useLen);
259 prv.lambda->useLen = 0;
260 }
261 if (!PARAMISNULL(prv.mu) && prv.mu->useLen != 0) {
262 BSL_SAL_CleanseData(prv.mu->value, prv.mu->useLen);
263 prv.mu->useLen = 0;
264 }
265 if (!PARAMISNULL(prv.n) && prv.n->useLen != 0) {
266 BSL_SAL_CleanseData(prv.n->value, prv.n->useLen);
267 prv.n->useLen = 0;
268 }
269 if (!PARAMISNULL(prv.n2) && prv.n2->useLen != 0) {
270 BSL_SAL_CleanseData(prv.n2->value, prv.n2->useLen);
271 prv.n2->useLen = 0;
272 }
273 return ret;
274 }
275
GetPubBasicCheck(const CRYPT_PAILLIER_Ctx * ctx,BSL_Param * para,CRYPT_PaillierPubParam * pub)276 static int32_t GetPubBasicCheck(const CRYPT_PAILLIER_Ctx *ctx, BSL_Param *para, CRYPT_PaillierPubParam *pub)
277 {
278 if (ctx == NULL || ctx->pubKey == NULL || para == NULL) {
279 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
280 return CRYPT_NULL_INPUT;
281 }
282 pub->n = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N);
283 pub->g = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_G);
284 pub->n2 = BSL_PARAM_FindParam(para, CRYPT_PARAM_PAILLIER_N2);
285 if (PARAMISNULL(pub->n) || PARAMISNULL(pub->g) || PARAMISNULL(pub->n2)) {
286 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
287 return CRYPT_NULL_INPUT;
288 }
289 return CRYPT_SUCCESS;
290 }
291
CRYPT_PAILLIER_GetPubKey(const CRYPT_PAILLIER_Ctx * ctx,BSL_Param * para)292 int32_t CRYPT_PAILLIER_GetPubKey(const CRYPT_PAILLIER_Ctx *ctx, BSL_Param *para)
293 {
294 CRYPT_PaillierPubParam pub = {0};
295 int32_t ret = GetPubBasicCheck(ctx, para, &pub);
296 if (ret != CRYPT_SUCCESS) {
297 BSL_ERR_PUSH_ERROR(ret);
298 return ret;
299 }
300
301 pub.g->useLen = pub.g->valueLen;
302 ret = BN_Bn2Bin(ctx->pubKey->g, pub.g->value, &(pub.g->useLen));
303 if (ret != CRYPT_SUCCESS) {
304 BSL_ERR_PUSH_ERROR(ret);
305 return ret;
306 }
307 pub.n->useLen = pub.n->valueLen;
308 ret = BN_Bn2Bin(ctx->pubKey->n, pub.n->value, &(pub.n->useLen));
309 if (ret != CRYPT_SUCCESS) {
310 BSL_ERR_PUSH_ERROR(ret);
311 return ret;
312 }
313 if (pub.n2 != NULL) {
314 pub.n2->useLen = pub.n2->valueLen;
315 ret = BN_Bn2Bin(ctx->pubKey->n2, pub.n2->value, &pub.n2->useLen);
316 if (ret != CRYPT_SUCCESS) {
317 BSL_ERR_PUSH_ERROR(ret);
318 }
319 }
320 return ret;
321 }
322
CRYPT_PAILLIER_GetSecBits(const CRYPT_PAILLIER_Ctx * ctx)323 int32_t CRYPT_PAILLIER_GetSecBits(const CRYPT_PAILLIER_Ctx *ctx)
324 {
325 if (ctx == NULL) {
326 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
327 return 0;
328 }
329 int32_t bits = (int32_t)CRYPT_PAILLIER_GetBits(ctx);
330 return BN_SecBits(bits, -1);
331 }
332
333 #endif /* HITLS_CRYPTO_PAILLIER */