2 * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * DH low level APIs are deprecated for public use, but still ok for
14 #include "internal/deprecated.h"
17 #include <openssl/bn.h>
18 #include <openssl/engine.h>
19 #include <openssl/obj_mac.h>
20 #include <openssl/core_names.h>
21 #include "internal/cryptlib.h"
22 #include "internal/refcount.h"
23 #include "crypto/evp.h"
24 #include "crypto/dh.h"
27 static DH
*dh_new_intern(ENGINE
*engine
, OPENSSL_CTX
*libctx
);
30 int DH_set_method(DH
*dh
, const DH_METHOD
*meth
)
33 * NB: The caller is specifically setting a method, so it's not up to us
34 * to deal with which ENGINE it comes from.
36 const DH_METHOD
*mtmp
;
40 #ifndef OPENSSL_NO_ENGINE
41 ENGINE_finish(dh
->engine
);
50 const DH_METHOD
*dh_get_method(const DH
*dh
)
57 return dh_new_intern(NULL
, NULL
);
60 DH
*DH_new_method(ENGINE
*engine
)
62 return dh_new_intern(engine
, NULL
);
64 #endif /* !FIPS_MODE */
66 DH
*dh_new_with_libctx(OPENSSL_CTX
*libctx
)
68 return dh_new_intern(NULL
, libctx
);
71 static DH
*dh_new_intern(ENGINE
*engine
, OPENSSL_CTX
*libctx
)
73 DH
*ret
= OPENSSL_zalloc(sizeof(*ret
));
76 DHerr(0, ERR_R_MALLOC_FAILURE
);
81 ret
->lock
= CRYPTO_THREAD_lock_new();
82 if (ret
->lock
== NULL
) {
83 DHerr(0, ERR_R_MALLOC_FAILURE
);
89 ret
->meth
= DH_get_default_method();
90 #if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
91 ret
->flags
= ret
->meth
->flags
; /* early default init */
93 if (!ENGINE_init(engine
)) {
94 DHerr(0, ERR_R_ENGINE_LIB
);
99 ret
->engine
= ENGINE_get_default_DH();
101 ret
->meth
= ENGINE_get_DH(ret
->engine
);
102 if (ret
->meth
== NULL
) {
103 DHerr(0, ERR_R_ENGINE_LIB
);
109 ret
->flags
= ret
->meth
->flags
;
112 if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH
, ret
, &ret
->ex_data
))
114 #endif /* FIPS_MODE */
116 if ((ret
->meth
->init
!= NULL
) && !ret
->meth
->init(ret
)) {
117 DHerr(0, ERR_R_INIT_FAIL
);
135 CRYPTO_DOWN_REF(&r
->references
, &i
, r
->lock
);
136 REF_PRINT_COUNT("DH", r
);
139 REF_ASSERT_ISNT(i
< 0);
141 if (r
->meth
!= NULL
&& r
->meth
->finish
!= NULL
)
143 #if !defined(FIPS_MODE)
144 # if !defined(OPENSSL_NO_ENGINE)
145 ENGINE_finish(r
->engine
);
147 CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH
, r
, &r
->ex_data
);
150 CRYPTO_THREAD_lock_free(r
->lock
);
152 ffc_params_cleanup(&r
->params
);
153 BN_clear_free(r
->pub_key
);
154 BN_clear_free(r
->priv_key
);
162 if (CRYPTO_UP_REF(&r
->references
, &i
, r
->lock
) <= 0)
165 REF_PRINT_COUNT("DH", r
);
166 REF_ASSERT_ISNT(i
< 2);
167 return ((i
> 1) ? 1 : 0);
171 int DH_set_ex_data(DH
*d
, int idx
, void *arg
)
173 return CRYPTO_set_ex_data(&d
->ex_data
, idx
, arg
);
176 void *DH_get_ex_data(const DH
*d
, int idx
)
178 return CRYPTO_get_ex_data(&d
->ex_data
, idx
);
182 int DH_bits(const DH
*dh
)
184 return BN_num_bits(dh
->params
.p
);
187 int DH_size(const DH
*dh
)
189 return BN_num_bytes(dh
->params
.p
);
192 int DH_security_bits(const DH
*dh
)
195 if (dh
->params
.q
!= NULL
)
196 N
= BN_num_bits(dh
->params
.q
);
201 return BN_security_bits(BN_num_bits(dh
->params
.p
), N
);
204 void DH_get0_pqg(const DH
*dh
,
205 const BIGNUM
**p
, const BIGNUM
**q
, const BIGNUM
**g
)
207 ffc_params_get0_pqg(&dh
->params
, p
, q
, g
);
210 int DH_set0_pqg(DH
*dh
, BIGNUM
*p
, BIGNUM
*q
, BIGNUM
*g
)
212 /* If the fields p and g in d are NULL, the corresponding input
213 * parameters MUST be non-NULL. q may remain NULL.
215 if ((dh
->params
.p
== NULL
&& p
== NULL
)
216 || (dh
->params
.g
== NULL
&& g
== NULL
))
219 ffc_params_set0_pqg(&dh
->params
, p
, q
, g
);
220 dh
->params
.nid
= NID_undef
;
222 * Check if this is a named group. If it finds a named group then the
223 * 'q' and 'length' value are either already set or are set by the
226 if (DH_get_nid(dh
) == NID_undef
) {
227 /* If its not a named group then set the 'length' if q is not NULL */
229 dh
->length
= BN_num_bits(q
);
235 long DH_get_length(const DH
*dh
)
240 int DH_set_length(DH
*dh
, long length
)
246 void DH_get0_key(const DH
*dh
, const BIGNUM
**pub_key
, const BIGNUM
**priv_key
)
249 *pub_key
= dh
->pub_key
;
250 if (priv_key
!= NULL
)
251 *priv_key
= dh
->priv_key
;
254 int DH_set0_key(DH
*dh
, BIGNUM
*pub_key
, BIGNUM
*priv_key
)
256 if (pub_key
!= NULL
) {
257 BN_clear_free(dh
->pub_key
);
258 dh
->pub_key
= pub_key
;
260 if (priv_key
!= NULL
) {
261 BN_clear_free(dh
->priv_key
);
262 dh
->priv_key
= priv_key
;
269 const BIGNUM
*DH_get0_p(const DH
*dh
)
274 const BIGNUM
*DH_get0_q(const DH
*dh
)
279 const BIGNUM
*DH_get0_g(const DH
*dh
)
284 const BIGNUM
*DH_get0_priv_key(const DH
*dh
)
289 const BIGNUM
*DH_get0_pub_key(const DH
*dh
)
294 void DH_clear_flags(DH
*dh
, int flags
)
299 int DH_test_flags(const DH
*dh
, int flags
)
301 return dh
->flags
& flags
;
304 void DH_set_flags(DH
*dh
, int flags
)
310 ENGINE
*DH_get0_engine(DH
*dh
)
314 #endif /*FIPS_MODE */
316 FFC_PARAMS
*dh_get0_params(DH
*dh
)
320 int dh_get0_nid(const DH
*dh
)
322 return dh
->params
.nid
;
325 int dh_ffc_params_fromdata(DH
*dh
, const OSSL_PARAM params
[])
332 ffc
= dh_get0_params(dh
);
336 ret
= ffc_params_fromdata(ffc
, params
);
344 static int dh_paramgen_check(EVP_PKEY_CTX
*ctx
)
346 if (ctx
== NULL
|| !EVP_PKEY_CTX_IS_GEN_OP(ctx
)) {
347 ERR_raise(ERR_LIB_EVP
, EVP_R_COMMAND_NOT_SUPPORTED
);
348 /* Uses the same return values as EVP_PKEY_CTX_ctrl */
351 /* If key type not DH return error */
352 if (ctx
->pmeth
!= NULL
353 && ctx
->pmeth
->pkey_id
!= EVP_PKEY_DH
354 && ctx
->pmeth
->pkey_id
!= EVP_PKEY_DHX
)
359 int EVP_PKEY_CTX_set_dh_paramgen_gindex(EVP_PKEY_CTX
*ctx
, int gindex
)
362 OSSL_PARAM params
[2], *p
= params
;
364 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
367 *p
++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GINDEX
, &gindex
);
368 *p
++ = OSSL_PARAM_construct_end();
370 return EVP_PKEY_CTX_set_params(ctx
, params
);
373 int EVP_PKEY_CTX_set_dh_paramgen_seed(EVP_PKEY_CTX
*ctx
,
374 const unsigned char *seed
,
378 OSSL_PARAM params
[2], *p
= params
;
380 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
383 *p
++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_FFC_SEED
,
384 (void *)seed
, seedlen
);
385 *p
++ = OSSL_PARAM_construct_end();
387 return EVP_PKEY_CTX_set_params(ctx
, params
);
390 int EVP_PKEY_CTX_set_dh_paramgen_type(EVP_PKEY_CTX
*ctx
, int typ
)
393 OSSL_PARAM params
[2], *p
= params
;
396 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
399 #if !defined(FIPS_MODE)
400 /* TODO(3.0): Remove this eventually when no more legacy */
401 if (ctx
->op
.keymgmt
.genctx
== NULL
)
402 return EVP_PKEY_CTX_ctrl(ctx
, EVP_PKEY_DH
, EVP_PKEY_OP_PARAMGEN
,
403 EVP_PKEY_CTRL_DH_PARAMGEN_TYPE
, typ
, NULL
);
406 name
= dh_gen_type_id2name(typ
);
409 *p
++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_TYPE
,
411 *p
++ = OSSL_PARAM_construct_end();
413 return EVP_PKEY_CTX_set_params(ctx
, params
);
416 int EVP_PKEY_CTX_set_dh_paramgen_prime_len(EVP_PKEY_CTX
*ctx
, int pbits
)
419 OSSL_PARAM params
[2], *p
= params
;
422 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
425 #if !defined(FIPS_MODE)
426 /* TODO(3.0): Remove this eventually when no more legacy */
427 if (ctx
->op
.keymgmt
.genctx
== NULL
)
428 return EVP_PKEY_CTX_ctrl(ctx
, EVP_PKEY_DH
, EVP_PKEY_OP_PARAMGEN
,
429 EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN
, pbits
,
432 *p
++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_PBITS
, &bits
);
433 *p
++ = OSSL_PARAM_construct_end();
434 return EVP_PKEY_CTX_set_params(ctx
, params
);
437 int EVP_PKEY_CTX_set_dh_paramgen_subprime_len(EVP_PKEY_CTX
*ctx
, int qbits
)
440 OSSL_PARAM params
[2], *p
= params
;
441 size_t bits2
= qbits
;
443 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
446 #if !defined(FIPS_MODE)
447 /* TODO(3.0): Remove this eventually when no more legacy */
448 if (ctx
->op
.keymgmt
.genctx
== NULL
)
449 return EVP_PKEY_CTX_ctrl(ctx
, EVP_PKEY_DH
, EVP_PKEY_OP_PARAMGEN
,
450 EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN
, qbits
,
453 *p
++ = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_FFC_QBITS
, &bits2
);
454 *p
++ = OSSL_PARAM_construct_end();
456 return EVP_PKEY_CTX_set_params(ctx
, params
);
459 int EVP_PKEY_CTX_set_dh_paramgen_generator(EVP_PKEY_CTX
*ctx
, int gen
)
462 OSSL_PARAM params
[2], *p
= params
;
464 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
467 #if !defined(FIPS_MODE)
468 /* TODO(3.0): Remove this eventually when no more legacy */
469 if (ctx
->op
.keymgmt
.genctx
== NULL
)
470 return EVP_PKEY_CTX_ctrl(ctx
, EVP_PKEY_DH
, EVP_PKEY_OP_PARAMGEN
,
471 EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR
, gen
, NULL
);
474 *p
++ = OSSL_PARAM_construct_int(OSSL_PKEY_PARAM_FFC_GENERATOR
, &gen
);
475 *p
++ = OSSL_PARAM_construct_end();
477 return EVP_PKEY_CTX_set_params(ctx
, params
);
480 int EVP_PKEY_CTX_set_dh_rfc5114(EVP_PKEY_CTX
*ctx
, int gen
)
483 OSSL_PARAM params
[2], *p
= params
;
486 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
489 #if !defined(FIPS_MODE)
490 /* TODO(3.0): Remove this eventually when no more legacy */
491 if (ctx
->op
.keymgmt
.genctx
== NULL
)
492 return EVP_PKEY_CTX_ctrl(ctx
, EVP_PKEY_DHX
, EVP_PKEY_OP_PARAMGEN
,
493 EVP_PKEY_CTRL_DH_RFC5114
, gen
, NULL
);
495 name
= ffc_named_group_from_uid(gen
);
499 *p
++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_GROUP
,
501 *p
++ = OSSL_PARAM_construct_end();
502 return EVP_PKEY_CTX_set_params(ctx
, params
);
505 int EVP_PKEY_CTX_set_dhx_rfc5114(EVP_PKEY_CTX
*ctx
, int gen
)
507 return EVP_PKEY_CTX_set_dh_rfc5114(ctx
, gen
);
510 int EVP_PKEY_CTX_set_dh_nid(EVP_PKEY_CTX
*ctx
, int nid
)
513 OSSL_PARAM params
[2], *p
= params
;
516 if ((ret
= dh_paramgen_check(ctx
)) <= 0)
519 #if !defined(FIPS_MODE)
520 /* TODO(3.0): Remove this eventually when no more legacy */
521 if (ctx
->op
.keymgmt
.genctx
== NULL
)
522 return EVP_PKEY_CTX_ctrl(ctx
, EVP_PKEY_DH
,
523 EVP_PKEY_OP_PARAMGEN
| EVP_PKEY_OP_KEYGEN
,
524 EVP_PKEY_CTRL_DH_NID
, nid
, NULL
);
526 name
= ffc_named_group_from_uid(nid
);
530 *p
++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_FFC_GROUP
,
532 *p
++ = OSSL_PARAM_construct_end();
533 return EVP_PKEY_CTX_set_params(ctx
, params
);