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