• 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_DH
18 
19 #include "crypt_errno.h"
20 #include "securec.h"
21 #include "bsl_sal.h"
22 #include "bsl_err_internal.h"
23 #include "crypt_bn.h"
24 #include "crypt_utils.h"
25 #include "crypt_dh.h"
26 #include "dh_local.h"
27 #include "sal_atomic.h"
28 #include "crypt_local_types.h"
29 #include "crypt_params_key.h"
30 
CRYPT_DH_NewCtx(void)31 CRYPT_DH_Ctx *CRYPT_DH_NewCtx(void)
32 {
33     CRYPT_DH_Ctx *ctx = BSL_SAL_Malloc(sizeof(CRYPT_DH_Ctx));
34     if (ctx == NULL) {
35         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
36         return NULL;
37     }
38     (void)memset_s(ctx, sizeof(CRYPT_DH_Ctx), 0, sizeof(CRYPT_DH_Ctx));
39     BSL_SAL_ReferencesInit(&(ctx->references));
40     return ctx;
41 }
42 
CRYPT_DH_NewCtxEx(void * libCtx)43 CRYPT_DH_Ctx *CRYPT_DH_NewCtxEx(void *libCtx)
44 {
45     CRYPT_DH_Ctx *ctx = CRYPT_DH_NewCtx();
46     if (ctx == NULL) {
47         return NULL;
48     }
49     ctx->libCtx = libCtx;
50     return ctx;
51 }
52 
ParaMemGet(uint32_t bits)53 static CRYPT_DH_Para *ParaMemGet(uint32_t bits)
54 {
55     CRYPT_DH_Para *para = BSL_SAL_Calloc(1u, sizeof(CRYPT_DH_Para));
56     if (para == NULL) {
57         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
58         return NULL;
59     }
60     para->p = BN_Create(bits);
61     para->g = BN_Create(bits);
62     para->id = CRYPT_PKEY_PARAID_MAX;
63     if (para->p == NULL || para->g == NULL) {
64         CRYPT_DH_FreePara(para);
65         BSL_ERR_PUSH_ERROR(CRYPT_DH_CREATE_PARA_FAIL);
66         return NULL;
67     }
68     return para;
69 }
70 
ValidateParamLength(const BSL_Param * param,uint32_t maxLen)71 static int32_t ValidateParamLength(const BSL_Param *param, uint32_t maxLen)
72 {
73     if (param == NULL || param->value == NULL || param->valueLen > maxLen || param->valueLen == 0) {
74         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
75         return CRYPT_DH_PARA_ERROR;
76     }
77     return CRYPT_SUCCESS;
78 }
79 
GetDhParam(const BSL_Param * params,int32_t paramId,uint32_t maxLen,const uint8_t ** value,uint32_t * valueLen)80 static int32_t GetDhParam(const BSL_Param *params, int32_t paramId, uint32_t maxLen,
81     const uint8_t **value, uint32_t *valueLen)
82 {
83     const BSL_Param *param = BSL_PARAM_FindConstParam(params, paramId);
84     int32_t ret = ValidateParamLength(param, maxLen);
85     if (ret != CRYPT_SUCCESS) {
86         return ret;
87     }
88 
89     *value = param->value;
90     *valueLen = param->valueLen;
91     return CRYPT_SUCCESS;
92 }
93 
InitDhPara(CRYPT_DH_Para * para,const uint8_t * p,uint32_t pLen,const uint8_t * g,uint32_t gLen)94 static int32_t InitDhPara(CRYPT_DH_Para *para, const uint8_t *p, uint32_t pLen,
95     const uint8_t *g, uint32_t gLen)
96 {
97     int32_t ret = BN_Bin2Bn(para->p, p, pLen);
98     if (ret != CRYPT_SUCCESS) {
99         BSL_ERR_PUSH_ERROR(ret);
100         return ret;
101     }
102 
103     ret = BN_Bin2Bn(para->g, g, gLen);
104     if (ret != CRYPT_SUCCESS) {
105         BSL_ERR_PUSH_ERROR(ret);
106     }
107     return ret;
108 }
109 
InitDhParaQ(CRYPT_DH_Para * para,const uint8_t * q,uint32_t qLen,uint32_t modBits)110 static int32_t InitDhParaQ(CRYPT_DH_Para *para, const uint8_t *q, uint32_t qLen, uint32_t modBits)
111 {
112     if (q == NULL) {
113         return CRYPT_SUCCESS;
114     }
115 
116     para->q = BN_Create(modBits);
117     if (para->q == NULL) {
118         BSL_ERR_PUSH_ERROR(CRYPT_DH_CREATE_PARA_FAIL);
119         return CRYPT_DH_CREATE_PARA_FAIL;
120     }
121 
122     int32_t ret = BN_Bin2Bn(para->q, q, qLen);
123     if (ret != CRYPT_SUCCESS) {
124         BSL_ERR_PUSH_ERROR(ret);
125     }
126     return ret;
127 }
128 
CRYPT_DH_NewPara(const BSL_Param * params)129 CRYPT_DH_Para *CRYPT_DH_NewPara(const BSL_Param *params)
130 {
131     if (params == NULL) {
132         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
133         return NULL;
134     }
135 
136     const uint8_t *p = NULL;
137     uint32_t pLen = 0;
138     int32_t ret = GetDhParam(params, CRYPT_PARAM_DH_P, BN_BITS_TO_BYTES(DH_MAX_PBITS), &p, &pLen);
139     if (ret != CRYPT_SUCCESS) {
140         return NULL;
141     }
142 
143     const uint8_t *g = NULL;
144     uint32_t gLen = 0;
145     ret = GetDhParam(params, CRYPT_PARAM_DH_G, pLen, &g, &gLen);
146     if (ret != CRYPT_SUCCESS) {
147         return NULL;
148     }
149 
150     const uint8_t *q = NULL;
151     uint32_t qLen = 0;
152     const BSL_Param *qParam = BSL_PARAM_FindConstParam(params, CRYPT_PARAM_DH_Q);
153     if (qParam != NULL) {
154         if (qParam->value == NULL && qParam->valueLen != 0) {
155             return NULL;
156         }
157         if (qParam->value != NULL) {
158             ret = ValidateParamLength(qParam, pLen);
159             if (ret != CRYPT_SUCCESS) {
160                 return NULL;
161             }
162             q = qParam->value;
163             qLen = qParam->valueLen;
164         }
165     }
166 
167     uint32_t modBits = BN_BYTES_TO_BITS(pLen);
168     CRYPT_DH_Para *para = ParaMemGet(modBits);
169     if (para == NULL) {
170         return NULL;
171     }
172 
173     ret = InitDhPara(para, p, pLen, g, gLen);
174     if (ret != CRYPT_SUCCESS) {
175         goto ERR;
176     }
177 
178     ret = InitDhParaQ(para, q, qLen, modBits);
179     if (ret != CRYPT_SUCCESS) {
180         goto ERR;
181     }
182 
183     para->id = CRYPT_PKEY_PARAID_MAX;
184     return para;
185 
186 ERR:
187     CRYPT_DH_FreePara(para);
188     return NULL;
189 }
190 
CRYPT_DH_FreePara(CRYPT_DH_Para * dhPara)191 void CRYPT_DH_FreePara(CRYPT_DH_Para *dhPara)
192 {
193     if (dhPara == NULL) {
194         return;
195     }
196     BN_Destroy(dhPara->p);
197     BN_Destroy(dhPara->q);
198     BN_Destroy(dhPara->g);
199     BSL_SAL_FREE(dhPara);
200 }
201 
CRYPT_DH_FreeCtx(CRYPT_DH_Ctx * ctx)202 void CRYPT_DH_FreeCtx(CRYPT_DH_Ctx *ctx)
203 {
204     if (ctx == NULL) {
205         return;
206     }
207     int val = 0;
208     BSL_SAL_AtomicDownReferences(&(ctx->references), &val);
209     if (val > 0) {
210         return;
211     }
212     CRYPT_DH_FreePara(ctx->para);
213     BN_Destroy(ctx->x);
214     BN_Destroy(ctx->y);
215     BSL_SAL_ReferencesFree(&(ctx->references));
216     BSL_SAL_FREE(ctx);
217 }
218 
ParaQCheck(BN_BigNum * q,BN_BigNum * r)219 static int32_t ParaQCheck(BN_BigNum *q, BN_BigNum *r)
220 {
221     // 1. Determine the length.
222     if (BN_Bits(q) < DH_MIN_QBITS) {
223         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
224         return CRYPT_DH_PARA_ERROR;
225     }
226     // 2. Parity and even judgment
227     if (BN_GetBit(q, 0) == 0) {
228         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
229         return CRYPT_DH_PARA_ERROR;
230     }
231     // 3. Compare q and r.
232     if (BN_Cmp(q, r) >= 0) {
233         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
234         return CRYPT_DH_PARA_ERROR;
235     }
236 
237     // 4. Check the pq multiple relationship.
238     BN_Optimizer *opt = BN_OptimizerCreate();
239     if (opt == NULL) {
240         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
241         return CRYPT_MEM_ALLOC_FAIL;
242     }
243     int32_t ret = BN_Div(NULL, r, r, q, opt);
244     BN_OptimizerDestroy(opt);
245     if (ret != CRYPT_SUCCESS) {
246         BSL_ERR_PUSH_ERROR(ret);
247         return ret;
248     }
249     // (p - 1) % q == 0
250     if (!BN_IsZero(r)) {
251         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
252         return CRYPT_DH_PARA_ERROR;
253     }
254     return CRYPT_SUCCESS;
255 }
256 
ParaDataCheck(const CRYPT_DH_Para * para)257 static int32_t ParaDataCheck(const CRYPT_DH_Para *para)
258 {
259     int32_t ret;
260     const BN_BigNum *p = para->p;
261     const BN_BigNum *g = para->g;
262     // 1. Determine the length.
263     uint32_t pBits = BN_Bits(p);
264     if (pBits < DH_MIN_PBITS || pBits > DH_MAX_PBITS) {
265         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
266         return CRYPT_DH_PARA_ERROR;
267     }
268     // 2. P parity and g value judgment
269     // p is an odd number
270     if (BN_GetBit(p, 0) == 0) {
271         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
272         return CRYPT_DH_PARA_ERROR;
273     }
274     // g != 0 && g != 1
275     if (BN_IsZero(g) || BN_IsOne(g)) {
276         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
277         return CRYPT_DH_PARA_ERROR;
278     }
279 
280     BN_BigNum *r = BN_Create(pBits + 1);
281     if (r == NULL) {
282         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
283         return CRYPT_MEM_ALLOC_FAIL;
284     }
285     // r = p - 1
286     ret = BN_SubLimb(r, p, 1);
287     if (ret != CRYPT_SUCCESS) {
288         BSL_ERR_PUSH_ERROR(ret);
289         goto EXIT;
290     }
291     // g < p - 1
292     if (BN_Cmp(g, r) >= 0) {
293         ret = CRYPT_DH_PARA_ERROR;
294         BSL_ERR_PUSH_ERROR(ret);
295         goto EXIT;
296     }
297     if (para->q != NULL) {
298         ret = ParaQCheck(para->q, r);
299     }
300 EXIT:
301     BN_Destroy(r);
302     return ret;
303 }
304 
ParaDup(const CRYPT_DH_Para * para)305 static CRYPT_DH_Para *ParaDup(const CRYPT_DH_Para *para)
306 {
307     CRYPT_DH_Para *ret = BSL_SAL_Malloc(sizeof(CRYPT_DH_Para));
308     if (ret == NULL) {
309         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
310         return NULL;
311     }
312     ret->p = BN_Dup(para->p);
313     ret->q = BN_Dup(para->q);
314     ret->g = BN_Dup(para->g);
315     ret->id = para->id;
316     if (ret->p == NULL || ret->g == NULL) {
317         CRYPT_DH_FreePara(ret);
318         BSL_ERR_PUSH_ERROR(CRYPT_DH_CREATE_PARA_FAIL);
319         return NULL;
320     }
321     if (para->q != NULL && ret->q == NULL) {
322         CRYPT_DH_FreePara(ret);
323         BSL_ERR_PUSH_ERROR(CRYPT_DH_CREATE_PARA_FAIL);
324         return NULL;
325     }
326     return ret;
327 }
328 
CRYPT_DH_DupCtx(CRYPT_DH_Ctx * ctx)329 CRYPT_DH_Ctx *CRYPT_DH_DupCtx(CRYPT_DH_Ctx *ctx)
330 {
331     if (ctx == NULL) {
332         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
333         return NULL;
334     }
335     CRYPT_DH_Ctx *newKeyCtx = BSL_SAL_Calloc(1, sizeof(CRYPT_DH_Ctx));
336     if (newKeyCtx == NULL) {
337         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
338         return NULL;
339     }
340     // If x, y and para is not empty, copy the value.
341     GOTO_ERR_IF_SRC_NOT_NULL(newKeyCtx->x, ctx->x, BN_Dup(ctx->x), CRYPT_MEM_ALLOC_FAIL);
342     GOTO_ERR_IF_SRC_NOT_NULL(newKeyCtx->y, ctx->y, BN_Dup(ctx->y), CRYPT_MEM_ALLOC_FAIL);
343     GOTO_ERR_IF_SRC_NOT_NULL(newKeyCtx->para, ctx->para, ParaDup(ctx->para), CRYPT_MEM_ALLOC_FAIL);
344     BSL_SAL_ReferencesInit(&(newKeyCtx->references));
345     return newKeyCtx;
346 
347 ERR:
348     CRYPT_DH_FreeCtx(newKeyCtx);
349     return NULL;
350 }
351 
CRYPT_DH_SetParaEx(CRYPT_DH_Ctx * ctx,CRYPT_DH_Para * para)352 int32_t CRYPT_DH_SetParaEx(CRYPT_DH_Ctx *ctx, CRYPT_DH_Para *para)
353 {
354     if (ctx == NULL || para == NULL) {
355         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
356         return CRYPT_NULL_INPUT;
357     }
358     int32_t ret = ParaDataCheck(para);
359     if (ret != CRYPT_SUCCESS) {
360         BSL_ERR_PUSH_ERROR(ret);
361         return ret;
362     }
363     BN_Destroy(ctx->x);
364     BN_Destroy(ctx->y);
365     CRYPT_DH_FreePara(ctx->para);
366     ctx->x = NULL;
367     ctx->y = NULL;
368     ctx->para = para;
369     return CRYPT_SUCCESS;
370 }
371 
CRYPT_DH_SetPara(CRYPT_DH_Ctx * ctx,const BSL_Param * para)372 int32_t CRYPT_DH_SetPara(CRYPT_DH_Ctx *ctx, const BSL_Param *para)
373 {
374     if (ctx == NULL) {
375         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
376         return CRYPT_NULL_INPUT;
377     }
378     CRYPT_DH_Para *dhPara = CRYPT_DH_NewPara(para);
379     if (dhPara == NULL) {
380         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_NEW_PARA_FAIL);
381         return CRYPT_EAL_ERR_NEW_PARA_FAIL;
382     }
383     int32_t ret = ParaDataCheck(dhPara);
384     if (ret != CRYPT_SUCCESS) {
385         CRYPT_DH_FreePara(dhPara);
386         BSL_ERR_PUSH_ERROR(ret);
387         return ret;
388     }
389     BN_Destroy(ctx->x);
390     BN_Destroy(ctx->y);
391     CRYPT_DH_FreePara(ctx->para);
392     ctx->x = NULL;
393     ctx->y = NULL;
394     ctx->para = dhPara;
395     return CRYPT_SUCCESS;
396 }
397 
GetDhParamP(const CRYPT_DH_Para * para,BSL_Param * param)398 static int32_t GetDhParamP(const CRYPT_DH_Para *para, BSL_Param *param)
399 {
400     BSL_Param *temp = BSL_PARAM_FindParam(param, CRYPT_PARAM_DH_P);
401     if (temp == NULL) {
402         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
403         return CRYPT_DH_PARA_ERROR;
404     }
405 
406     temp->useLen = temp->valueLen;
407     int32_t ret = BN_Bn2Bin(para->p, temp->value, &temp->useLen);
408     if (ret != CRYPT_SUCCESS) {
409         BSL_ERR_PUSH_ERROR(ret);
410     }
411     return ret;
412 }
413 
GetDhParamQ(const CRYPT_DH_Para * para,BSL_Param * param)414 static int32_t GetDhParamQ(const CRYPT_DH_Para *para, BSL_Param *param)
415 {
416     BSL_Param *temp = BSL_PARAM_FindParam(param, CRYPT_PARAM_DH_Q);
417     if (temp == NULL) {
418         return CRYPT_SUCCESS;
419     }
420 
421     if (para->q == NULL) {
422         temp->useLen = 0;
423         return CRYPT_SUCCESS;
424     }
425 
426     temp->useLen = temp->valueLen;
427     int32_t ret = BN_Bn2Bin(para->q, temp->value, &temp->useLen);
428     if (ret != CRYPT_SUCCESS) {
429         BSL_ERR_PUSH_ERROR(ret);
430     }
431     return ret;
432 }
433 
GetDhParamG(const CRYPT_DH_Para * para,BSL_Param * param)434 static int32_t GetDhParamG(const CRYPT_DH_Para *para, BSL_Param *param)
435 {
436     BSL_Param *temp = BSL_PARAM_FindParam(param, CRYPT_PARAM_DH_G);
437     if (temp == NULL) {
438         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
439         return CRYPT_DH_PARA_ERROR;
440     }
441 
442     temp->useLen = temp->valueLen;
443     int32_t ret = BN_Bn2Bin(para->g, temp->value, &temp->useLen);
444     if (ret != CRYPT_SUCCESS) {
445         BSL_ERR_PUSH_ERROR(ret);
446     }
447     return ret;
448 }
449 
CRYPT_DH_GetPara(const CRYPT_DH_Ctx * ctx,BSL_Param * param)450 int32_t CRYPT_DH_GetPara(const CRYPT_DH_Ctx *ctx, BSL_Param *param)
451 {
452     if (ctx == NULL || param == NULL) {
453         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
454         return CRYPT_NULL_INPUT;
455     }
456     if (ctx->para == NULL) {
457         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
458         return CRYPT_DH_PARA_ERROR;
459     }
460 
461     int32_t ret = GetDhParamP(ctx->para, param);
462     if (ret != CRYPT_SUCCESS) {
463         return ret;
464     }
465 
466     ret = GetDhParamQ(ctx->para, param);
467     if (ret != CRYPT_SUCCESS) {
468         return ret;
469     }
470 
471     return GetDhParamG(ctx->para, param);
472 }
473 
PubCheck(const BN_BigNum * y,const BN_BigNum * minP)474 static int32_t PubCheck(const BN_BigNum *y, const BN_BigNum *minP)
475 {
476     // y != 0, y != 1
477     if (BN_IsZero(y) || BN_IsOne(y)) {
478         BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
479         return CRYPT_DH_KEYINFO_ERROR;
480     }
481     // y < p - 1
482     if (BN_Cmp(y, minP) >= 0) {
483         BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
484         return CRYPT_DH_KEYINFO_ERROR;
485     }
486     return CRYPT_SUCCESS;
487 }
488 
489 // Get p-2 or q-1
GetXLimb(BN_BigNum * xLimb,const BN_BigNum * p,const BN_BigNum * q)490 static int32_t GetXLimb(BN_BigNum *xLimb, const BN_BigNum *p, const BN_BigNum *q)
491 {
492     if (q != NULL) {
493         // xLimb = q - 1
494         return BN_SubLimb(xLimb, q, 1);
495     }
496     // xLimb = p - 2
497     return BN_SubLimb(xLimb, p, 2);
498 }
499 
RefreshCtx(CRYPT_DH_Ctx * dhCtx,BN_BigNum * x,BN_BigNum * y,int32_t ret)500 static void RefreshCtx(CRYPT_DH_Ctx *dhCtx, BN_BigNum *x, BN_BigNum *y, int32_t ret)
501 {
502     if (ret == CRYPT_SUCCESS) {
503         BN_Destroy(dhCtx->x);
504         BN_Destroy(dhCtx->y);
505         dhCtx->x = x;
506         dhCtx->y = y;
507     } else {
508         BN_Destroy(x);
509         BN_Destroy(y);
510     }
511 }
512 
513 /* SP800-56Ar3 5.6.1.1.4 Key-Pair Generation by Testing Candidates */
DH_GenSp80056ATestCandidates(CRYPT_DH_Ctx * ctx)514 static int32_t DH_GenSp80056ATestCandidates(CRYPT_DH_Ctx *ctx)
515 {
516     int32_t ret;
517     uint32_t bits = BN_Bits(ctx->para->p);
518     uint32_t qbits = BN_Bits(ctx->para->q);
519     /* If s is not the maximum security strength that can be support by (p, q, g), then return an error. */
520     uint32_t s = (uint32_t)CRYPT_DH_GetSecBits(ctx);
521     if (bits == 0 || qbits == 0 || s == 0) {
522         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
523         return CRYPT_DH_PARA_ERROR;
524     }
525     /* 2*s <= n <= len(q), set n = 2*s */
526     uint32_t n = 2 * s;
527     BN_BigNum *x = BN_Create(bits);
528     BN_BigNum *y = BN_Create(bits);
529     BN_BigNum *twoPowN = BN_Create(n);
530     BN_Mont *mont = BN_MontCreate(ctx->para->p);
531     BN_BigNum *m = ctx->para->q;
532     BN_Optimizer *opt = BN_OptimizerCreate();
533     if (x == NULL || y == NULL || mont == NULL || opt == NULL || twoPowN == NULL) {
534         ret = CRYPT_MEM_ALLOC_FAIL;
535         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
536         goto ERR;
537     }
538     ret = BN_SetLimb(twoPowN, 1);
539     if (ret != CRYPT_SUCCESS) {
540         BSL_ERR_PUSH_ERROR(ret);
541         goto ERR;
542     }
543     ret = BN_Lshift(twoPowN, twoPowN, n);
544     if (ret != CRYPT_SUCCESS) {
545         BSL_ERR_PUSH_ERROR(ret);
546         goto ERR;
547     }
548     /* Set M = min(2^N, q), the minimum of 2^N and q. */
549     if (BN_Cmp(twoPowN, m) < 0) {
550         m = twoPowN;
551     }
552     for (int32_t cnt = 0; cnt < CRYPT_DH_TRY_CNT_MAX; cnt++) {
553         /* c in the interval [0, 2N - 1] */
554         ret = BN_RandRangeEx(ctx->libCtx, x, twoPowN);
555         if (ret != CRYPT_SUCCESS) {
556             BSL_ERR_PUSH_ERROR(ret);
557             goto ERR;
558         }
559         /* x = c + 1 */
560         ret = BN_AddLimb(x, x, 1);
561         if (ret != CRYPT_SUCCESS) {
562             BSL_ERR_PUSH_ERROR(ret);
563             goto ERR;
564         }
565         /* If c > M - 2, (i.e. c + 1 >= M) continue */
566         if (BN_Cmp(x, m) >= 0) {
567             continue;
568         }
569         ret = BN_MontExpConsttime(y, ctx->para->g, x, mont, opt);
570         if (ret != CRYPT_SUCCESS) {
571             BSL_ERR_PUSH_ERROR(ret);
572         }
573         goto ERR; // The function exits successfully.
574     }
575     ret = CRYPT_DH_RAND_GENERATE_ERROR;
576     BSL_ERR_PUSH_ERROR(ret);
577 ERR:
578     RefreshCtx(ctx, x, y, ret);
579     BN_Destroy(twoPowN);
580     BN_MontDestroy(mont);
581     BN_OptimizerDestroy(opt);
582     return ret;
583 }
584 
DH_GenSp80056ASafePrime(CRYPT_DH_Ctx * ctx)585 static int32_t DH_GenSp80056ASafePrime(CRYPT_DH_Ctx *ctx)
586 {
587     int32_t ret;
588     uint32_t bits = BN_Bits(ctx->para->p);
589     BN_BigNum *x = BN_Create(bits);
590     BN_BigNum *y = BN_Create(bits);
591     BN_BigNum *minP = BN_Create(bits);
592     BN_BigNum *xLimb = BN_Create(bits);
593     BN_Mont *mont = BN_MontCreate(ctx->para->p);
594     BN_Optimizer *opt = BN_OptimizerCreate();
595     if (x == NULL || y == NULL || minP == NULL || xLimb == NULL || mont == NULL || opt == NULL) {
596         ret = CRYPT_MEM_ALLOC_FAIL;
597         BSL_ERR_PUSH_ERROR(ret);
598         goto EXIT;
599     }
600     ret = BN_SubLimb(minP, ctx->para->p, 1);
601     if (ret != CRYPT_SUCCESS) {
602         BSL_ERR_PUSH_ERROR(ret);
603         goto EXIT;
604     }
605     ret = GetXLimb(xLimb, ctx->para->p, ctx->para->q);
606     if (ret != CRYPT_SUCCESS) {
607         BSL_ERR_PUSH_ERROR(ret);
608         goto EXIT;
609     }
610     for (int32_t cnt = 0; cnt < CRYPT_DH_TRY_CNT_MAX; cnt++) {
611         /*  Generate private key x for [1, q-1] or [1, p-2] */
612         ret = BN_RandRangeEx(ctx->libCtx, x, xLimb);
613         if (ret != CRYPT_SUCCESS) {
614             BSL_ERR_PUSH_ERROR(ret);
615             goto EXIT;
616         }
617         ret = BN_AddLimb(x, x, 1);
618         if (ret != CRYPT_SUCCESS) {
619             BSL_ERR_PUSH_ERROR(ret);
620             goto EXIT;
621         }
622         /* Calculate the public key y. */
623         ret = BN_MontExpConsttime(y, ctx->para->g, x, mont, opt);
624         if (ret != CRYPT_SUCCESS) {
625             BSL_ERR_PUSH_ERROR(ret);
626             goto EXIT;
627         }
628         /* Check whether the public key meets the requirements. If not, try to generate the key again. */
629         // y != 0, y != 1, y < p - 1
630         if (BN_IsZero(y) || BN_IsOne(y) || BN_Cmp(y, minP) >= 0) {
631             continue;
632         }
633         goto EXIT; // The function exits successfully.
634     }
635     ret = CRYPT_DH_RAND_GENERATE_ERROR;
636     BSL_ERR_PUSH_ERROR(ret);
637 EXIT:
638     RefreshCtx(ctx, x, y, ret);
639     BN_Destroy(minP);
640     BN_Destroy(xLimb);
641     BN_MontDestroy(mont);
642     BN_OptimizerDestroy(opt);
643     return ret;
644 }
645 
CRYPT_DH_Gen(CRYPT_DH_Ctx * ctx)646 int32_t CRYPT_DH_Gen(CRYPT_DH_Ctx *ctx)
647 {
648     if (ctx == NULL || ctx->para == NULL) {
649         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
650         return CRYPT_DH_PARA_ERROR;
651     }
652     int32_t s = CRYPT_DH_GetSecBits(ctx);
653     if (ctx->para->q != NULL && s != 0) {
654         return DH_GenSp80056ATestCandidates(ctx);
655     }
656     return DH_GenSp80056ASafePrime(ctx);
657 }
658 
ComputeShareKeyInputCheck(const CRYPT_DH_Ctx * ctx,const CRYPT_DH_Ctx * pubKey,const uint8_t * shareKey,const uint32_t * shareKeyLen)659 static int32_t ComputeShareKeyInputCheck(const CRYPT_DH_Ctx *ctx, const CRYPT_DH_Ctx *pubKey,
660     const uint8_t *shareKey, const uint32_t *shareKeyLen)
661 {
662     if (ctx == NULL || pubKey == NULL || shareKey == NULL || shareKeyLen == NULL) {
663         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
664         return CRYPT_NULL_INPUT;
665     }
666     if (ctx->para == NULL) {
667         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
668         return CRYPT_DH_PARA_ERROR;
669     }
670     if (ctx->x == NULL || pubKey->y == NULL) {
671         BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
672         return CRYPT_DH_KEYINFO_ERROR;
673     }
674     if (BN_Bytes(ctx->para->p) > *shareKeyLen) {
675         BSL_ERR_PUSH_ERROR(CRYPT_DH_BUFF_LEN_NOT_ENOUGH);
676         return CRYPT_DH_BUFF_LEN_NOT_ENOUGH;
677     }
678     return CRYPT_SUCCESS;
679 }
680 
CheckAndFillZero(uint8_t * shareKey,uint32_t * shareKeyLen,uint32_t bytes)681 static void CheckAndFillZero(uint8_t *shareKey, uint32_t *shareKeyLen, uint32_t bytes)
682 {
683     int32_t i;
684     if (*shareKeyLen == bytes) { // (*shareKeyLen > bytes) is not possible
685         return;
686     }
687     uint32_t fill = bytes - *shareKeyLen;
688     for (i = (int32_t)*shareKeyLen - 1; i >= 0; i--) {
689         shareKey[i + (int32_t)fill] = shareKey[i];
690     }
691     for (i = 0; i < (int32_t)fill; i++) {
692         shareKey[i] = 0;
693     }
694     *shareKeyLen = bytes;
695 }
696 
CRYPT_DH_ComputeShareKey(const CRYPT_DH_Ctx * ctx,const CRYPT_DH_Ctx * pubKey,uint8_t * shareKey,uint32_t * shareKeyLen)697 int32_t CRYPT_DH_ComputeShareKey(const CRYPT_DH_Ctx *ctx, const CRYPT_DH_Ctx *pubKey,
698     uint8_t *shareKey, uint32_t *shareKeyLen)
699 {
700     uint32_t bytes = 0;
701     int32_t ret = ComputeShareKeyInputCheck(ctx, pubKey, shareKey, shareKeyLen);
702     if (ret != CRYPT_SUCCESS) {
703         return ret;
704     }
705     uint32_t bits = BN_Bits(ctx->para->p);
706     BN_BigNum *tmp = BN_Create(bits);
707     BN_Mont *mont = BN_MontCreate(ctx->para->p);
708     BN_Optimizer *opt = BN_OptimizerCreate();
709     if (tmp == NULL || mont == NULL || opt == NULL) {
710         ret = CRYPT_MEM_ALLOC_FAIL;
711         BSL_ERR_PUSH_ERROR(ret);
712         goto EXIT;
713     }
714     ret = BN_SubLimb(tmp, ctx->para->p, 1);
715     if (ret != CRYPT_SUCCESS) {
716         BSL_ERR_PUSH_ERROR(ret);
717         goto EXIT;
718     }
719     /* Check whether the public key meets the requirements. */
720     ret = PubCheck(pubKey->y, tmp);
721     if (ret != CRYPT_SUCCESS) {
722         BSL_ERR_PUSH_ERROR(ret);
723         goto EXIT;
724     }
725     ret = BN_MontExpConsttime(tmp, pubKey->y, ctx->x, mont, opt);
726     if (ret != CRYPT_SUCCESS) {
727         BSL_ERR_PUSH_ERROR(ret);
728         goto EXIT;
729     }
730     ret = BN_Bn2Bin(tmp, shareKey, shareKeyLen);
731     if (ret != CRYPT_SUCCESS) {
732         BSL_ERR_PUSH_ERROR(ret);
733         goto EXIT;
734     }
735     // no need to filled zero in the leading.
736     if ((ctx->flags & CRYPT_DH_NO_PADZERO) == 0) {
737         bytes = BN_BITS_TO_BYTES(bits);
738         CheckAndFillZero(shareKey, shareKeyLen, bytes);
739     }
740 EXIT:
741     BN_Destroy(tmp);
742     BN_MontDestroy(mont);
743     BN_OptimizerDestroy(opt);
744     return ret;
745 }
746 
PrvLenCheck(const CRYPT_DH_Ctx * ctx,const BSL_Param * prv)747 static int32_t PrvLenCheck(const CRYPT_DH_Ctx *ctx, const BSL_Param *prv)
748 {
749     if (ctx->para->q != NULL) {
750         if (BN_Bytes(ctx->para->q) < prv->valueLen) {
751             BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
752             return CRYPT_DH_KEYINFO_ERROR;
753         }
754     } else {
755         if (BN_Bytes(ctx->para->p) < prv->valueLen) {
756             BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
757             return CRYPT_DH_KEYINFO_ERROR;
758         }
759     }
760     return CRYPT_SUCCESS;
761 }
762 
CRYPT_DH_SetPrvKey(CRYPT_DH_Ctx * ctx,const BSL_Param * para)763 int32_t CRYPT_DH_SetPrvKey(CRYPT_DH_Ctx *ctx, const BSL_Param *para)
764 {
765     if (ctx == NULL || para == NULL) {
766         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
767         return CRYPT_NULL_INPUT;
768     }
769     const BSL_Param *prv = BSL_PARAM_FindConstParam(para, CRYPT_PARAM_DH_PRVKEY);
770     if (prv == NULL || prv->value == NULL || prv->valueLen == 0) {
771         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
772         return CRYPT_NULL_INPUT;
773     }
774     if (ctx->para == NULL) {
775         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
776         return CRYPT_DH_PARA_ERROR;
777     }
778     int32_t ret = PrvLenCheck(ctx, prv);
779     if (ret != CRYPT_SUCCESS) {
780         return ret;
781     }
782     BN_BigNum *bnX = BN_Create(BN_BYTES_TO_BITS(prv->valueLen));
783     BN_BigNum *xLimb = BN_Create(BN_Bits(ctx->para->p) + 1);
784     if (bnX == NULL || xLimb == NULL) {
785         ret = CRYPT_MEM_ALLOC_FAIL;
786         BSL_ERR_PUSH_ERROR(ret);
787         goto ERR;
788     }
789     ret = GetXLimb(xLimb, ctx->para->p, ctx->para->q);
790     if (ret != CRYPT_SUCCESS) {
791         BSL_ERR_PUSH_ERROR(ret);
792         goto ERR;
793     }
794     ret = BN_Bin2Bn(bnX, prv->value, prv->valueLen);
795     if (ret != CRYPT_SUCCESS) {
796         BSL_ERR_PUSH_ERROR(ret);
797         goto ERR;
798     }
799     // Satisfy x <= q - 1 or x <= p - 2
800     if (BN_Cmp(bnX, xLimb) > 0) {
801         ret = CRYPT_DH_KEYINFO_ERROR;
802         BSL_ERR_PUSH_ERROR(ret);
803         goto ERR;
804     }
805 
806     // x != 0
807     if (BN_IsZero(bnX)) {
808         ret = CRYPT_DH_KEYINFO_ERROR;
809         BSL_ERR_PUSH_ERROR(ret);
810         goto ERR;
811     }
812     BN_Destroy(xLimb);
813     BN_Destroy(ctx->x);
814     ctx->x = bnX;
815     return ret;
816 ERR:
817     BN_Destroy(bnX);
818     BN_Destroy(xLimb);
819     return ret;
820 }
821 
822 // No parameter information is required for setting the public key.
823 // Therefore, the validity of the public key is not checked during the setting.
824 // The validity of the public key is checked during the calculation of the shared key.
CRYPT_DH_SetPubKey(CRYPT_DH_Ctx * ctx,const BSL_Param * para)825 int32_t CRYPT_DH_SetPubKey(CRYPT_DH_Ctx *ctx, const BSL_Param *para)
826 {
827     if (ctx == NULL || para == NULL) {
828         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
829         return CRYPT_NULL_INPUT;
830     }
831     // assume that the two scenarios will not coexist.
832     const BSL_Param *pub = BSL_PARAM_FindConstParam(para, CRYPT_PARAM_DH_PUBKEY);
833     if (pub == NULL) {
834         pub = BSL_PARAM_FindConstParam(para, CRYPT_PARAM_PKEY_ENCODE_PUBKEY);
835     }
836 
837     if (pub == NULL || pub->value == NULL || pub->valueLen == 0) {
838         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
839         return CRYPT_NULL_INPUT;
840     }
841     if (pub->valueLen > BN_BITS_TO_BYTES(DH_MAX_PBITS)) {
842         BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
843         return CRYPT_DH_KEYINFO_ERROR;
844     }
845     BN_BigNum *bnY = BN_Create(BN_BYTES_TO_BITS(pub->valueLen));
846     if (bnY == NULL) {
847         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
848         return CRYPT_MEM_ALLOC_FAIL;
849     }
850     int32_t ret = BN_Bin2Bn(bnY, pub->value, pub->valueLen);
851     if (ret != CRYPT_SUCCESS) {
852         BSL_ERR_PUSH_ERROR(ret);
853         goto ERR;
854     }
855 
856     BN_Destroy(ctx->y);
857     ctx->y = bnY;
858     return ret;
859 ERR:
860     BN_Destroy(bnY);
861     return ret;
862 }
863 
CRYPT_DH_GetPrvKey(const CRYPT_DH_Ctx * ctx,BSL_Param * para)864 int32_t CRYPT_DH_GetPrvKey(const CRYPT_DH_Ctx *ctx, BSL_Param *para)
865 {
866     if (ctx == NULL || para == NULL) {
867         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
868         return CRYPT_NULL_INPUT;
869     }
870     BSL_Param *prv = BSL_PARAM_FindParam(para, CRYPT_PARAM_DH_PRVKEY);
871     if (prv == NULL || prv->value == NULL) {
872         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
873         return CRYPT_NULL_INPUT;
874     }
875     if (ctx->x == NULL) {
876         BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
877         return CRYPT_DH_KEYINFO_ERROR;
878     }
879     if (ctx->para->q != NULL) {
880         if (BN_Bytes(ctx->para->q) > prv->valueLen) {
881             BSL_ERR_PUSH_ERROR(CRYPT_DH_BUFF_LEN_NOT_ENOUGH);
882             return CRYPT_DH_BUFF_LEN_NOT_ENOUGH;
883         }
884     } else {
885         if (BN_Bytes(ctx->para->p) > prv->valueLen) {
886             BSL_ERR_PUSH_ERROR(CRYPT_DH_BUFF_LEN_NOT_ENOUGH);
887             return CRYPT_DH_BUFF_LEN_NOT_ENOUGH;
888         }
889     }
890     uint32_t useLen = prv->valueLen;
891     int32_t ret = BN_Bn2Bin(ctx->x, prv->value, &(useLen));
892     if (ret != CRYPT_SUCCESS) {
893         BSL_ERR_PUSH_ERROR(ret);
894         return ret;
895     }
896     prv->useLen = useLen;
897     return CRYPT_SUCCESS;
898 }
899 
CRYPT_DH_GetPubKey(const CRYPT_DH_Ctx * ctx,BSL_Param * para)900 int32_t CRYPT_DH_GetPubKey(const CRYPT_DH_Ctx *ctx, BSL_Param *para)
901 {
902     if (ctx == NULL || para == NULL) {
903         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
904         return CRYPT_NULL_INPUT;
905     }
906     // assume that the two scenarios will not coexist.
907     BSL_Param *pub = BSL_PARAM_FindParam(para, CRYPT_PARAM_DH_PUBKEY);
908     if (pub == NULL) {
909         pub = BSL_PARAM_FindParam(para, CRYPT_PARAM_PKEY_ENCODE_PUBKEY);
910     }
911 
912     if (pub == NULL || pub->value == NULL) {
913         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
914         return CRYPT_NULL_INPUT;
915     }
916     if (ctx->para == NULL || ctx->para->p == NULL) {
917         BSL_ERR_PUSH_ERROR(CRYPT_DH_PARA_ERROR);
918         return CRYPT_DH_PARA_ERROR;
919     }
920     if (ctx->y == NULL) {
921         BSL_ERR_PUSH_ERROR(CRYPT_DH_KEYINFO_ERROR);
922         return CRYPT_DH_KEYINFO_ERROR;
923     }
924     uint32_t pubLen = BN_Bytes(ctx->para->p);
925     if (pubLen > pub->valueLen) {
926         BSL_ERR_PUSH_ERROR(CRYPT_DH_BUFF_LEN_NOT_ENOUGH);
927         return CRYPT_DH_BUFF_LEN_NOT_ENOUGH;
928     }
929     // RFC 8446 requires the dh public value should be encoded as a big-endian integer and padded to
930     // the left with zeros to the size of p in bytes.
931     int32_t ret = BN_Bn2BinFixZero(ctx->y, pub->value, pubLen);
932     if (ret != CRYPT_SUCCESS) {
933         BSL_ERR_PUSH_ERROR(ret);
934         return ret;
935     }
936     pub->useLen = pubLen;
937     return CRYPT_SUCCESS;
938 }
939 
CRYPT_DH_GetBits(const CRYPT_DH_Ctx * ctx)940 uint32_t CRYPT_DH_GetBits(const CRYPT_DH_Ctx *ctx)
941 {
942     if (ctx == NULL) {
943         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
944         return 0;
945     }
946     if (ctx->para == NULL) {
947         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
948         return 0;
949     }
950     return BN_Bits(ctx->para->p);
951 }
952 
CRYPT_DH_GetPrvKeyLen(const CRYPT_DH_Ctx * ctx)953 static uint32_t CRYPT_DH_GetPrvKeyLen(const CRYPT_DH_Ctx *ctx)
954 {
955     return BN_Bytes(ctx->x);
956 }
957 
CRYPT_DH_GetPubKeyLen(const CRYPT_DH_Ctx * ctx)958 static uint32_t CRYPT_DH_GetPubKeyLen(const CRYPT_DH_Ctx *ctx)
959 {
960     if (ctx->para != NULL) {
961         return BN_Bytes(ctx->para->p);
962     }
963     if (ctx->y != NULL) {
964         return BN_Bytes(ctx->y);
965     }
966     BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
967     return 0;
968 }
969 
CRYPT_DH_GetSharedKeyLen(const CRYPT_DH_Ctx * ctx)970 static uint32_t CRYPT_DH_GetSharedKeyLen(const CRYPT_DH_Ctx *ctx)
971 {
972     if (ctx->para != NULL) {
973         return BN_Bytes(ctx->para->p);
974     }
975     BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
976     return 0;
977 }
978 
CRYPT_DH_Cmp(const CRYPT_DH_Ctx * a,const CRYPT_DH_Ctx * b)979 int32_t CRYPT_DH_Cmp(const CRYPT_DH_Ctx *a, const CRYPT_DH_Ctx *b)
980 {
981     RETURN_RET_IF(a == NULL || b == NULL, CRYPT_NULL_INPUT);
982 
983     RETURN_RET_IF(a->y == NULL || b->y == NULL, CRYPT_DH_KEYINFO_ERROR);
984     RETURN_RET_IF(BN_Cmp(a->y, b->y) != 0, CRYPT_DH_PUBKEY_NOT_EQUAL);
985 
986     // para must be both null and non-null.
987     RETURN_RET_IF((a->para == NULL) != (b->para == NULL), CRYPT_DH_PARA_ERROR);
988     if (a->para != NULL) {
989         RETURN_RET_IF(BN_Cmp(a->para->p, b->para->p) != 0 ||
990                       BN_Cmp(a->para->q, b->para->q) != 0 ||
991                       BN_Cmp(a->para->g, b->para->g) != 0,
992                       CRYPT_DH_PARA_NOT_EQUAL);
993     }
994     return CRYPT_SUCCESS;
995 }
996 
CRYPT_DH_SetParamById(CRYPT_DH_Ctx * ctx,CRYPT_PKEY_ParaId id)997 int32_t CRYPT_DH_SetParamById(CRYPT_DH_Ctx *ctx, CRYPT_PKEY_ParaId id)
998 {
999     CRYPT_DH_Para *para = CRYPT_DH_NewParaById(id);
1000     if (para == NULL) {
1001         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_NEW_PARA_FAIL);
1002         return CRYPT_EAL_ERR_NEW_PARA_FAIL;
1003     }
1004     int32_t ret = CRYPT_DH_SetParaEx(ctx, para);
1005     if (ret != CRYPT_SUCCESS) {
1006         CRYPT_DH_FreePara(para);
1007     }
1008     return ret;
1009 }
1010 
CRYPT_DH_GetLen(const CRYPT_DH_Ctx * ctx,GetLenFunc func,void * val,uint32_t len)1011 static int32_t CRYPT_DH_GetLen(const CRYPT_DH_Ctx *ctx, GetLenFunc func, void *val, uint32_t len)
1012 {
1013     if (val == NULL || len != sizeof(int32_t)) {
1014         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
1015         return CRYPT_NULL_INPUT;
1016     }
1017 
1018     *(int32_t *)val = func(ctx);
1019     return CRYPT_SUCCESS;
1020 }
1021 
CRYPT_DH_SetFlag(CRYPT_DH_Ctx * ctx,const void * val,uint32_t len)1022 static int32_t CRYPT_DH_SetFlag(CRYPT_DH_Ctx *ctx, const void *val, uint32_t len)
1023 {
1024     if (val == NULL) {
1025         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
1026         return CRYPT_NULL_INPUT;
1027     }
1028     if (len != sizeof(uint32_t)) {
1029         BSL_ERR_PUSH_ERROR(CRYPT_DH_SET_FLAG_LEN_ERROR);
1030         return CRYPT_DH_SET_FLAG_LEN_ERROR;
1031     }
1032     uint32_t flag = *(const uint32_t *)val;
1033     if (flag == 0 || flag >= CRYPT_DH_MAXFLAG) {
1034         BSL_ERR_PUSH_ERROR(CRYPT_DH_FLAG_NOT_SUPPORT_ERROR);
1035         return CRYPT_DH_FLAG_NOT_SUPPORT_ERROR;
1036     }
1037     ctx->flags |= flag;
1038     return CRYPT_SUCCESS;
1039 }
1040 
CRYPT_DH_Ctrl(CRYPT_DH_Ctx * ctx,int32_t opt,void * val,uint32_t len)1041 int32_t CRYPT_DH_Ctrl(CRYPT_DH_Ctx *ctx, int32_t opt, void *val, uint32_t len)
1042 {
1043     if (ctx == NULL) {
1044         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
1045         return CRYPT_NULL_INPUT;
1046     }
1047     switch (opt) {
1048         case CRYPT_CTRL_GET_PARAID:
1049             return CRYPT_DH_GetLen(ctx, (GetLenFunc)CRYPT_DH_GetParaId, val, len);
1050         case CRYPT_CTRL_GET_BITS:
1051             return CRYPT_DH_GetLen(ctx, (GetLenFunc)CRYPT_DH_GetBits, val, len);
1052         case CRYPT_CTRL_GET_SECBITS:
1053             return CRYPT_DH_GetLen(ctx, (GetLenFunc)CRYPT_DH_GetSecBits, val, len);
1054         case CRYPT_CTRL_GET_PUBKEY_LEN:
1055             return GetUintCtrl(ctx, val, len, (GetUintCallBack)CRYPT_DH_GetPubKeyLen);
1056         case CRYPT_CTRL_GET_PRVKEY_LEN:
1057             return GetUintCtrl(ctx, val, len, (GetUintCallBack)CRYPT_DH_GetPrvKeyLen);
1058         case CRYPT_CTRL_GET_SHARED_KEY_LEN:
1059             return GetUintCtrl(ctx, val, len, (GetUintCallBack)CRYPT_DH_GetSharedKeyLen);
1060         case CRYPT_CTRL_SET_PARA_BY_ID:
1061             return CRYPT_DH_SetParamById(ctx, *(CRYPT_PKEY_ParaId *)val);
1062         case CRYPT_CTRL_SET_DH_FLAG:
1063             return CRYPT_DH_SetFlag(ctx, val, len);
1064         case CRYPT_CTRL_UP_REFERENCES:
1065             if (val == NULL || len != (uint32_t)sizeof(int)) {
1066                 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
1067                 return CRYPT_INVALID_ARG;
1068             }
1069             return BSL_SAL_AtomicUpReferences(&(ctx->references), (int *)val);
1070         default:
1071             break;
1072     }
1073     BSL_ERR_PUSH_ERROR(CRYPT_DH_UNSUPPORTED_CTRL_OPTION);
1074     return CRYPT_DH_UNSUPPORTED_CTRL_OPTION;
1075 }
1076 
1077 /**
1078  * @ingroup dh
1079  * @brief dh get security bits
1080  *
1081  * @param ctx [IN] dh Context structure
1082  *
1083  * @retval security bits
1084  */
CRYPT_DH_GetSecBits(const CRYPT_DH_Ctx * ctx)1085 int32_t CRYPT_DH_GetSecBits(const CRYPT_DH_Ctx *ctx)
1086 {
1087     if (ctx == NULL || ctx->para == NULL || ctx->para->p == NULL) {
1088         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
1089         return 0;
1090     }
1091     if (ctx->para->q == NULL) {
1092         return BN_SecBits(BN_Bits(ctx->para->p), -1);
1093     }
1094     return BN_SecBits(BN_Bits(ctx->para->p), BN_Bits(ctx->para->q));
1095 }
1096 
1097 #endif /* HITLS_CRYPTO_DH */
1098