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