# info > EVP_KEYMGMT-DH

---
type: CommandReference
command: EVP_PKEY-DH
mode: man
section: 7SSL
source: man-pages
---

## Quick Reference

- `EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)` -- create DH context for key generation
- `EVP_PKEY_keygen_init(pctx)` -- initialize key generation
- `EVP_PKEY_generate(pctx, &pkey)` -- generate DH key
- `EVP_PKEY_paramgen_init(pctx)` -- initialize domain parameter generation
- `EVP_PKEY_todata(key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS, &params)` -- extract domain parameters
- `EVP_PKEY_fromdata(ctx, &key, OSSL_KEYMGMT_SELECT_ALL, params)` -- create key with merged parameters
- `EVP_PKEY_param_check(ctx)` -- validate domain parameters
- `OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0)` -- set named safe-prime group

## Name

EVP_PKEY DH and DHX keytype and algorithm support

## Synopsis

DH and DHX key types for EVP_PKEY, supporting Diffie-Hellman key agreement with safe-prime groups or FIPS 186-type parameters. DH uses PKCS#3 format (p, g), DHX uses X9.42 format (p, g, q) and is required for FIPS 186-4.

## Options

### Domain parameters (common to DH and DHX)

- `"group"` (OSSL_PKEY_PARAM_GROUP_NAME) `<UTF8 string>` -- set named safe-prime group. Supported groups: `ffdhe2048`, `ffdhe3072`, `ffdhe4096`, `ffdhe6144`, `ffdhe8192`, `modp_2048`, `modp_3072`, `modp_4096`, `modp_6144`, `modp_8192`. Default provider also: `modp_1536`, `dh_1024_160`, `dh_2048_224`, `dh_2048_256`.
- `"encoded-pub-key"` (OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY) `<octet string>` -- get/set encoded public key for TLS key exchange.

### DH-only domain parameters

- `"safeprime-generator"` (OSSL_PKEY_PARAM_DH_GENERATOR) `<integer>` -- generator for safe prime generation (default 2). Not allowed in FIPS.

### Key generation parameters

- `"type"` (OSSL_PKEY_PARAM_FFC_TYPE) `<UTF8 string>` -- generation type: `"fips186_4"`, `"default"`, `"fips186_2"`, `"group"` (choose named group by pbits), `"generator"` (DH only, see safeprime-generator).
- `"pbits"` (OSSL_PKEY_PARAM_FFC_PBITS) `<unsigned integer>` -- size of prime p in bits. For `fips186_4`: 2048; `fips186_2`: 1024; `group`: 2048, 3072, 4096, 6144, or 8192.
- `"priv_len"` (OSSL_PKEY_PARAM_DH_PRIV_LEN) `<integer>` -- maximum private key length in bits. Default is `BN_num_bits(q)`. Minimum is 2 * s, where s is security strength (112, 128, 152, 176, 200 for key sizes 2048, 3072, 4096, 6144, 8192).

## Examples

### Generate DH key with named safe-prime group

c
int priv_len = 2 * 112;
OSSL_PARAM params[3];
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);

params[0] = OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0);
/* "priv_len" is optional */
params[1] = OSSL_PARAM_construct_int("priv_len", &priv_len);
params[2] = OSSL_PARAM_construct_end();

EVP_PKEY_keygen_init(pctx);
EVP_PKEY_CTX_set_params(pctx, params);
EVP_PKEY_generate(pctx, &pkey);
...
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(pctx);
### Generate DHX domain parameters (FIPS 186-4)

c
int gindex = 2;
unsigned int pbits = 2048;
unsigned int qbits = 256;
OSSL_PARAM params[6];
EVP_PKEY *param_key = NULL;
EVP_PKEY_CTX *pctx = NULL;

pctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
EVP_PKEY_paramgen_init(pctx);

params[0] = OSSL_PARAM_construct_uint("pbits", &pbits);
params[1] = OSSL_PARAM_construct_uint("qbits", &qbits);
params[2] = OSSL_PARAM_construct_int("gindex", &gindex);
params[3] = OSSL_PARAM_construct_utf8_string("type", "fips186_4", 0);
params[4] = OSSL_PARAM_construct_utf8_string("digest", "SHA256", 0);
params[5] = OSSL_PARAM_construct_end();
EVP_PKEY_CTX_set_params(pctx, params);

EVP_PKEY_generate(pctx, &param_key);

EVP_PKEY_print_params(bio_out, param_key, 0, NULL);
...
EVP_PKEY_free(param_key);
EVP_PKEY_CTX_free(pctx);
### Generate DH key from domain parameters

c
EVP_PKEY *key = NULL;
EVP_PKEY_CTX *gctx = EVP_PKEY_CTX_new_from_pkey(NULL, param_key, NULL);

EVP_PKEY_keygen_init(gctx);
EVP_PKEY_generate(gctx, &key);
EVP_PKEY_print_private(bio_out, key, 0, NULL);
...
EVP_PKEY_free(key);
EVP_PKEY_CTX_free(gctx);
### Validate FIPS 186-4 DHX domain parameters with extra generation data

c
EVP_PKEY *received_domp = ...; /* parameters received and decoded */
unsigned char *seed = ...;     /* and additional parameters received */
size_t seedlen = ...;          /* by other means, required */
int gindex = ...;              /* for the validation */
int pcounter = ...;
int hindex = ...;
OSSL_PARAM extra_params[4];
OSSL_PARAM *domain_params = NULL;
OSSL_PARAM *merged_params = NULL;
EVP_PKEY_CTX *ctx = NULL, *validate_ctx = NULL;
EVP_PKEY *complete_domp = NULL;

EVP_PKEY_todata(received_domp, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
                &domain_params);
extra_params[0] = OSSL_PARAM_construct_octet_string("seed", seed, seedlen);
/*
 * NOTE: For unverifiable g use "hindex" instead of "gindex"
 * extra_params[1] = OSSL_PARAM_construct_int("hindex", &hindex);
 */
extra_params[1] = OSSL_PARAM_construct_int("gindex", &gindex);
extra_params[2] = OSSL_PARAM_construct_int("pcounter", &pcounter);
extra_params[3] = OSSL_PARAM_construct_end();
merged_params = OSSL_PARAM_merge(domain_params, extra_params);

ctx = EVP_PKEY_CTX_new_from_name(NULL, "DHX", NULL);
EVP_PKEY_fromdata_init(ctx);
EVP_PKEY_fromdata(ctx, &complete_domp, OSSL_KEYMGMT_SELECT_ALL,
                  merged_params);

validate_ctx = EVP_PKEY_CTX_new_from_pkey(NULL, complete_domp, NULL);
if (EVP_PKEY_param_check(validate_ctx) > 0)
    /* validation_passed(); */
else
    /* validation_failed(); */

OSSL_PARAM_free(domain_params);
OSSL_PARAM_free(merged_params);
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_CTX_free(validate_ctx);
EVP_PKEY_free(complete_domp);
## Conforming to

- RFC 7919 (TLS ffdhe named safe prime groups)
- RFC 3526 (IKE modp named safe prime groups)
- RFC 5114 (Additional DH named groups: `dh_1024_160`, `dh_2048_224`, `dh_2048_256`)
- SP800-56Ar3 §5.5.1.1, Appendix D
- FIPS 186-4 §A.1.1.2, §A.2.3, §A.2.1

## See Also

- [EVP_PKEY-FFC(7)](https://www.openssl.org/docs/man3.0/man7/EVP_PKEY-FFC.html)
- [EVP_KEYEXCH-DH(7)](https://www.openssl.org/docs/man3.0/man7/EVP_KEYEXCH-DH.html)
- [EVP_PKEY(3)](https://www.openssl.org/docs/man3.0/man3/EVP_PKEY.html)
- [provider-keymgmt(7)](https://www.openssl.org/docs/man3.0/man7/provider-keymgmt.html)
- [EVP_KEYMGMT(3)](https://www.openssl.org/docs/man3.0/man3/EVP_KEYMGMT.html)
- [OSSL_PROVIDER-default(7)](https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-default.html)
- [OSSL_PROVIDER-FIPS(7)](https://www.openssl.org/docs/man3.0/man7/OSSL_PROVIDER-FIPS.html)