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_types.h"
20 #include "crypt_elgamal.h"
21 #include "crypt_utils.h"
22 #include "bsl_err_internal.h"
23 #include "elgamal_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 *p; /**< ElGamal private key parameter marked as p */
31 BSL_Param *g; /**< ElGamal private key parameter marked as g */
32 BSL_Param *x; /**< ElGamal private key parameter marked as x */
33 } CRYPT_ElGamalPrvParam;
34
35 typedef struct {
36 BSL_Param *p; /**< ElGamal public key parameter marked as p */
37 BSL_Param *g; /**< ElGamal public key parameter marked as g */
38 BSL_Param *y; /**< ElGamal public key parameter marked as y */
39 BSL_Param *q; /**< ElGamal public key parameter marked as y */
40 } CRYPT_ElGamalPubParam;
41
42 #define PARAMISNULL(a) (a == NULL || a->value == NULL)
43
SetPrvPara(const CRYPT_ELGAMAL_PrvKey * prvKey,const CRYPT_ElGamalPrvParam * prv)44 static int32_t SetPrvPara(const CRYPT_ELGAMAL_PrvKey *prvKey, const CRYPT_ElGamalPrvParam *prv)
45 {
46 int32_t ret = BN_Bin2Bn(prvKey->p, prv->p->value, prv->p->valueLen);
47 if (ret != CRYPT_SUCCESS) {
48 BSL_ERR_PUSH_ERROR(ret);
49 return ret;
50 }
51
52 uint32_t bnBits = BN_Bits(prvKey->p);
53 if (bnBits > ELGAMAL_MAX_MODULUS_BITS || bnBits <= 0) {
54 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_KEY_BITS);
55 return CRYPT_ELGAMAL_ERR_KEY_BITS;
56 }
57
58 ret = BN_Bin2Bn(prvKey->g, prv->g->value, prv->g->valueLen);
59 if (ret != CRYPT_SUCCESS) {
60 BSL_ERR_PUSH_ERROR(ret);
61 return ret;
62 }
63
64 ret = BN_Bin2Bn(prvKey->x, prv->x->value, prv->x->valueLen);
65 if (ret != CRYPT_SUCCESS) {
66 BSL_ERR_PUSH_ERROR(ret);
67 return ret;
68 }
69
70 return ret;
71 }
72
SetPrvBasicCheck(const CRYPT_ELGAMAL_Ctx * ctx,BSL_Param * para,CRYPT_ElGamalPrvParam * prv)73 static int32_t SetPrvBasicCheck(const CRYPT_ELGAMAL_Ctx *ctx, BSL_Param *para, CRYPT_ElGamalPrvParam *prv)
74 {
75 if (ctx == NULL || para == NULL) {
76 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
77 return CRYPT_NULL_INPUT;
78 }
79
80 prv->p = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_P);
81 prv->g = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_G);
82 prv->x = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_X);
83 if (PARAMISNULL(prv->p) || PARAMISNULL(prv->g) || PARAMISNULL(prv->x) ||
84 prv->p->valueLen == 0 || prv->g->valueLen == 0 || prv->x->valueLen == 0) {
85 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_INPUT_VALUE);
86 return CRYPT_ELGAMAL_ERR_INPUT_VALUE;
87 }
88
89 return CRYPT_SUCCESS;
90 }
91
CRYPT_ELGAMAL_SetPrvKey(CRYPT_ELGAMAL_Ctx * ctx,const BSL_Param * para)92 int32_t CRYPT_ELGAMAL_SetPrvKey(CRYPT_ELGAMAL_Ctx *ctx, const BSL_Param *para)
93 {
94 CRYPT_ElGamalPrvParam prv = {0};
95 int32_t ret = SetPrvBasicCheck(ctx, (BSL_Param *)(uintptr_t)para, &prv);
96 if (ret != CRYPT_SUCCESS) {
97 return ret;
98 }
99
100 CRYPT_ELGAMAL_Ctx *newCtx = CRYPT_ELGAMAL_NewCtx();
101 if (newCtx == NULL) {
102 return CRYPT_MEM_ALLOC_FAIL;
103 }
104
105 newCtx->prvKey = ElGamal_NewPrvKey(prv.p->valueLen * 8); // Bit length is obtained by multiplying byte length by 8.
106 if (newCtx->prvKey == NULL) {
107 ret = CRYPT_MEM_ALLOC_FAIL;
108 BSL_ERR_PUSH_ERROR(ret);
109 goto ERR;
110 }
111
112 ret = SetPrvPara(newCtx->prvKey, &prv);
113 if (ret != CRYPT_SUCCESS) {
114 BSL_ERR_PUSH_ERROR(ret);
115 goto ERR;
116 }
117
118 ELGAMAL_FREE_PRV_KEY(ctx->prvKey);
119 ctx->prvKey = newCtx->prvKey;
120
121 BSL_SAL_ReferencesFree(&(newCtx->references));
122 BSL_SAL_FREE(newCtx);
123
124 return ret;
125 ERR:
126 CRYPT_ELGAMAL_FreeCtx(newCtx);
127 return ret;
128 }
129
SetPubBasicCheck(const CRYPT_ELGAMAL_Ctx * ctx,BSL_Param * para,CRYPT_ElGamalPubParam * pub)130 static int32_t SetPubBasicCheck(const CRYPT_ELGAMAL_Ctx *ctx, BSL_Param *para, CRYPT_ElGamalPubParam *pub)
131 {
132 if (ctx == NULL || para == NULL) {
133 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
134 return CRYPT_NULL_INPUT;
135 }
136 pub->p = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_P);
137 pub->g = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_G);
138 pub->y = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_Y);
139 pub->q = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_Q);
140 if (PARAMISNULL(pub->p) || PARAMISNULL(pub->g) || PARAMISNULL(pub->y) || PARAMISNULL(pub->q)) {
141 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
142 return CRYPT_NULL_INPUT;
143 }
144 return CRYPT_SUCCESS;
145 }
146
CRYPT_ELGAMAL_SetPubKey(CRYPT_ELGAMAL_Ctx * ctx,const BSL_Param * para)147 int32_t CRYPT_ELGAMAL_SetPubKey(CRYPT_ELGAMAL_Ctx *ctx, const BSL_Param *para)
148 {
149 CRYPT_ElGamalPubParam pub = {0};
150 int32_t ret = SetPubBasicCheck(ctx, (BSL_Param *)(uintptr_t)para, &pub);
151 if (ret != CRYPT_SUCCESS) {
152 BSL_ERR_PUSH_ERROR(ret);
153 return ret;
154 }
155
156 CRYPT_ELGAMAL_PubKey *newPub = NULL;
157 /* Bit length is obtained by multiplying byte length by 8. */
158 newPub = ElGamal_NewPubKey(pub.p->valueLen * 8);
159 if (newPub == NULL) {
160 return CRYPT_MEM_ALLOC_FAIL;
161 }
162 GOTO_ERR_IF(BN_Bin2Bn(newPub->p, pub.p->value, pub.p->valueLen), ret);
163 uint32_t bnBits = BN_Bits(newPub->p);
164 if (bnBits > ELGAMAL_MAX_MODULUS_BITS || bnBits <= 0) {
165 ret = CRYPT_ELGAMAL_ERR_KEY_BITS;
166 BSL_ERR_PUSH_ERROR(ret);
167 goto ERR;
168 }
169 GOTO_ERR_IF(BN_Bin2Bn(newPub->g, pub.g->value, pub.g->valueLen), ret);
170 GOTO_ERR_IF(BN_Bin2Bn(newPub->y, pub.y->value, pub.y->valueLen), ret);
171 GOTO_ERR_IF(BN_Bin2Bn(newPub->q, pub.q->value, pub.q->valueLen), ret);
172
173 ELGAMAL_FREE_PUB_KEY(ctx->pubKey);
174 ctx->pubKey = newPub;
175 return ret;
176 ERR:
177 ELGAMAL_FREE_PUB_KEY(newPub);
178 return ret;
179 }
180
GetPrvBasicCheck(const CRYPT_ELGAMAL_Ctx * ctx,BSL_Param * para,CRYPT_ElGamalPrvParam * prv)181 static int32_t GetPrvBasicCheck(const CRYPT_ELGAMAL_Ctx *ctx, BSL_Param *para, CRYPT_ElGamalPrvParam *prv)
182 {
183 if (ctx == NULL || ctx->prvKey == NULL || para == NULL) {
184 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
185 return CRYPT_NULL_INPUT;
186 }
187 prv->p = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_P);
188 prv->g = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_G);
189 prv->x = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_X);
190
191 if (PARAMISNULL(prv->x)) {
192 BSL_ERR_PUSH_ERROR(CRYPT_ELGAMAL_ERR_INPUT_VALUE);
193 return CRYPT_ELGAMAL_ERR_INPUT_VALUE;
194 }
195 return CRYPT_SUCCESS;
196 }
197
CRYPT_ELGAMAL_GetPrvKey(const CRYPT_ELGAMAL_Ctx * ctx,BSL_Param * para)198 int32_t CRYPT_ELGAMAL_GetPrvKey(const CRYPT_ELGAMAL_Ctx *ctx, BSL_Param *para)
199 {
200 CRYPT_ElGamalPrvParam prv = {0};
201 int32_t ret = GetPrvBasicCheck(ctx, para, &prv);
202 if (ret != CRYPT_SUCCESS) {
203 return ret;
204 }
205 if (!PARAMISNULL(prv.p)) {
206 prv.p->useLen = prv.p->valueLen;
207 GOTO_ERR_IF(BN_Bn2Bin(ctx->prvKey->p, prv.p->value, &(prv.p->useLen)), ret);
208 }
209 if (!PARAMISNULL(prv.g)) {
210 prv.g->useLen = prv.g->valueLen;
211 GOTO_ERR_IF(BN_Bn2Bin(ctx->prvKey->g, prv.g->value, &(prv.g->useLen)), ret);
212 }
213
214 prv.x->useLen = prv.x->valueLen;
215 GOTO_ERR_IF(BN_Bn2Bin(ctx->prvKey->x, prv.x->value, &(prv.x->useLen)), ret);
216
217 return CRYPT_SUCCESS;
218 ERR:
219 if (!PARAMISNULL(prv.p) && prv.p->useLen != 0) {
220 BSL_SAL_CleanseData(prv.p->value, prv.p->useLen);
221 prv.p->useLen = 0;
222 }
223 if (!PARAMISNULL(prv.g) && prv.g->useLen != 0) {
224 BSL_SAL_CleanseData(prv.g->value, prv.g->useLen);
225 prv.g->useLen = 0;
226 }
227 if (prv.x->useLen != 0) {
228 BSL_SAL_CleanseData(prv.x->value, prv.x->useLen);
229 prv.x->useLen = 0;
230 }
231
232 return ret;
233 }
234
GetPubBasicCheck(const CRYPT_ELGAMAL_Ctx * ctx,BSL_Param * para,CRYPT_ElGamalPubParam * pub)235 static int32_t GetPubBasicCheck(const CRYPT_ELGAMAL_Ctx *ctx, BSL_Param *para, CRYPT_ElGamalPubParam *pub)
236 {
237 if (ctx == NULL || ctx->pubKey == NULL || para == NULL) {
238 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
239 return CRYPT_NULL_INPUT;
240 }
241 pub->p = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_P);
242 pub->g = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_G);
243 pub->y = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_Y);
244 pub->q = BSL_PARAM_FindParam(para, CRYPT_PARAM_ELGAMAL_Q);
245 if (PARAMISNULL(pub->p) || PARAMISNULL(pub->g) || PARAMISNULL(pub->y) || PARAMISNULL(pub->q)) {
246 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
247 return CRYPT_NULL_INPUT;
248 }
249 return CRYPT_SUCCESS;
250 }
251
CRYPT_ELGAMAL_GetPubKey(const CRYPT_ELGAMAL_Ctx * ctx,BSL_Param * para)252 int32_t CRYPT_ELGAMAL_GetPubKey(const CRYPT_ELGAMAL_Ctx *ctx, BSL_Param *para)
253 {
254 CRYPT_ElGamalPubParam pub = {0};
255 int32_t ret = GetPubBasicCheck(ctx, para, &pub);
256 if (ret != CRYPT_SUCCESS) {
257 BSL_ERR_PUSH_ERROR(ret);
258 return ret;
259 }
260
261 pub.g->useLen = pub.g->valueLen;
262 ret = BN_Bn2Bin(ctx->pubKey->g, pub.g->value, &(pub.g->useLen));
263 if (ret != CRYPT_SUCCESS) {
264 BSL_ERR_PUSH_ERROR(ret);
265 return ret;
266 }
267
268 pub.p->useLen = pub.p->valueLen;
269 ret = BN_Bn2Bin(ctx->pubKey->p, pub.p->value, &(pub.p->useLen));
270 if (ret != CRYPT_SUCCESS) {
271 BSL_ERR_PUSH_ERROR(ret);
272 return ret;
273 }
274
275 pub.q->useLen = pub.q->valueLen;
276 ret = BN_Bn2Bin(ctx->pubKey->q, pub.q->value, &(pub.q->useLen));
277 if (ret != CRYPT_SUCCESS) {
278 BSL_ERR_PUSH_ERROR(ret);
279 return ret;
280 }
281
282 pub.y->useLen = pub.y->valueLen;
283 ret = BN_Bn2Bin(ctx->pubKey->y, pub.y->value, &pub.y->useLen);
284 if (ret != CRYPT_SUCCESS) {
285 BSL_ERR_PUSH_ERROR(ret);
286 }
287
288 return ret;
289 }
290
CRYPT_ELGAMAL_GetSecBits(const CRYPT_ELGAMAL_Ctx * ctx)291 int32_t CRYPT_ELGAMAL_GetSecBits(const CRYPT_ELGAMAL_Ctx *ctx)
292 {
293 if (ctx == NULL) {
294 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
295 return 0;
296 }
297 int32_t bits = (int32_t)CRYPT_ELGAMAL_GetBits(ctx);
298 return BN_SecBits(bits, -1);
299 }
300
301 #endif /* HITLS_CRYPTO_ELGAMAL */