See EVP_PKEY-FFC(7) for more information about FFC keys.
The DH key type uses PKCS#3 format which saves p and g, but not the q value. The DHX key type uses X9.42 format which saves the value of q and this must be used for FIPS186-4. If key validation is required, users should be aware of the nuances associated with FIPS186-4 style parameters as discussed in ``DH key validation''.
The following values can be used by the OpenSSL's default and FIPS providers: ``ffdhe2048'', ``ffdhe3072'', ``ffdhe4096'', ``ffdhe6144'', ``ffdhe8192'', ``modp_2048'', ``modp_3072'', ``modp_4096'', ``modp_6144'', ``modp_8192''.
The following additional values can also be used by OpenSSL's default provider: ``modp_1536'', ``dh_1024_160'', ``dh_2048_224'', ``dh_2048_256''.
DH/DHX named groups can be easily validated since the parameters are well known. For protocols that only transfer p and g the value of q can also be retrieved.
Randomly generated safe primes are not allowed by FIPS, so setting this value for the OpenSSL FIPS provider will instead choose a named safe prime group based on the size of p.
For ``fips186_4'' this must be 2048. For ``fips186_2'' this must be 1024. For ``group'' this can be any one of 2048, 3072, 4096, 6144 or 8192.
For DH keys, EVP_PKEY_param_check(3) behaves in the following way: The OpenSSL FIPS provider tests if the parameters are either an approved safe prime group OR that the FFC parameters conform to FIPS186-4 as defined in SP800-56Ar3 Assurances of Domain-Parameter Validity. The OpenSSL default provider uses simpler checks that allows there to be no q value for backwards compatibility.
For DH keys, EVP_PKEY_param_check_quick(3) is equivalent to EVP_PKEY_param_check(3).
For DH keys, EVP_PKEY_public_check(3) conforms to SP800-56Ar3 FFC Full Public-Key Validation.
For DH keys, EVP_PKEY_public_check_quick(3) conforms to SP800-56Ar3 FFC Partial Public-Key Validation when the DH key is an approved named safe prime group, otherwise it is the same as EVP_PKEY_public_check(3).
For DH Keys, EVP_PKEY_private_check(3) tests that the private key is in the correct range according to SP800-56Ar3. The OpenSSL FIPS provider requires the value of q to be set (note that this is set for named safe prime groups). For backwards compatibility the OpenSSL default provider only requires p to be set.
For DH keys, EVP_PKEY_pairwise_check(3) conforms to SP800-56Ar3 Owner Assurance of Pair-wise Consistency.
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL);
A DH key can be generated with a named safe prime group by calling:
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);
DHX domain parameters can be generated according to FIPS186-4 by calling:
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, ¶m_key); EVP_PKEY_print_params(bio_out, param_key, 0, NULL); ... EVP_PKEY_free(param_key); EVP_PKEY_CTX_free(pctx);
A DH key can be generated using domain parameters by calling:
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);
To validate FIPS186-4 DHX domain parameters decoded from PEM or DER data, additional values used during generation may be required to be set into the key.
EVP_PKEY_todata(), OSSL_PARAM_merge(), and EVP_PKEY_fromdata() are useful to add these parameters to the original key or domain parameters before the actual validation. In production code the return values should be checked.
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);
The following sections of SP800-56Ar3:
The following sections of FIPS186-4:
Licensed under the Apache License 2.0 (the ``License''). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at <https://www.openssl.org/source/license.html>.