summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2021-04-15 18:25:17 +1000
committerTomas Mraz <tomas@openssl.org>2021-04-26 19:52:11 +0200
commitf1ffaaeece5efb7d2f4859a59e3164edf9b4b769 (patch)
treea125dfda9f44ef0702f8bae025ccec829eb33652
parent6c9bc258d2e9e7b500236a1c696da1f384f0b907 (diff)
Fixes related to separation of DH and DHX types
Fix dh_rfc5114 option in genpkey. Fixes #14145 Fixes #13956 Fixes #13952 Fixes #13871 Fixes #14054 Fixes #14444 Updated documentation for app to indicate what options are available for DH and DHX keys. DH and DHX now have different keymanager gen_set_params() methods. Added CHANGES entry to indicate the breaking change. Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/14883)
-rw-r--r--CHANGES.md7
-rw-r--r--crypto/dh/dh_pmeth.c43
-rw-r--r--crypto/evp/ctrl_params_translate.c104
-rw-r--r--crypto/evp/dh_support.c29
-rw-r--r--crypto/evp/p_lib.c33
-rw-r--r--crypto/ffc/ffc_dh.c4
-rw-r--r--doc/man1/openssl-genpkey.pod.in186
-rw-r--r--doc/man7/EVP_PKEY-DH.pod60
-rw-r--r--doc/man7/EVP_PKEY-FFC.pod36
-rw-r--r--include/crypto/dh.h2
-rw-r--r--providers/implementations/keymgmt/dh_kmgmt.c125
-rw-r--r--test/recipes/15-test_gendh.t33
-rw-r--r--test/recipes/15-test_gendhparam.t170
-rw-r--r--test/recipes/20-test_dhparam_check.t14
-rw-r--r--test/recipes/20-test_dhparam_check_data/valid/dh_5114_1.pem (renamed from test/recipes/20-test_dhparam_check_data/invalid/dh5114_1_pkcs3.pem)0
-rw-r--r--test/recipes/20-test_dhparam_check_data/valid/dh_5114_2.pem (renamed from test/recipes/20-test_dhparam_check_data/invalid/dh5114_2_pkcs3.pem)0
-rw-r--r--test/recipes/20-test_dhparam_check_data/valid/dh_5114_3.pem (renamed from test/recipes/20-test_dhparam_check_data/invalid/dh5114_3_pkcs3.pem)0
-rw-r--r--test/recipes/20-test_dhparam_check_data/valid/dhx_5114_2.pem14
18 files changed, 638 insertions, 222 deletions
diff --git a/CHANGES.md b/CHANGES.md
index d2d9e01f35..480c4091a9 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -23,6 +23,13 @@ OpenSSL 3.0
### Changes between 1.1.1 and 3.0 [xx XXX xxxx]
+ * For the key types DH and DHX the allowed settable parameters are now different.
+ Previously (in 1.1.1) these conflicting parameters were allowed, but will now
+ result in errors. See EVP_PKEY-DH(7) for further details. This affects the
+ behaviour of openssl-genpkey(1) for DH parameter generation.
+
+ *Shane Lontis*
+
* The default manual page suffix ($MANSUFFIX) has been changed to "ossl"
*Matt Caswell*
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index affe40a53c..78d46aba22 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -35,7 +35,6 @@ typedef struct {
int pad;
/* message digest used for parameter generation */
const EVP_MD *md;
- int rfc5114_param;
int param_nid;
/* Keygen callback info */
int gentmp[2];
@@ -98,7 +97,6 @@ static int pkey_dh_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
dctx->paramgen_type = sctx->paramgen_type;
dctx->pad = sctx->pad;
dctx->md = sctx->md;
- dctx->rfc5114_param = sctx->rfc5114_param;
dctx->param_nid = sctx->param_nid;
dctx->kdf_type = sctx->kdf_type;
@@ -156,11 +154,11 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
case EVP_PKEY_CTRL_DH_RFC5114:
if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
return -2;
- dctx->rfc5114_param = p1;
+ dctx->param_nid = p1;
return 1;
case EVP_PKEY_CTRL_DH_NID:
- if (p1 <= 0 || dctx->rfc5114_param != 0)
+ if (p1 <= 0 || dctx->param_nid != NID_undef)
return -2;
dctx->param_nid = p1;
return 1;
@@ -233,11 +231,12 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
}
if (strcmp(type, "dh_rfc5114") == 0) {
DH_PKEY_CTX *dctx = ctx->data;
- int len;
- len = atoi(value);
- if (len < 0 || len > 3)
+ int id;
+
+ id = atoi(value);
+ if (id < 0 || id > 3)
return -2;
- dctx->rfc5114_param = len;
+ dctx->param_nid = id;
return 1;
}
if (strcmp(type, "dh_param") == 0) {
@@ -331,36 +330,16 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
/*
* Look for a safe prime group for key establishment. Which uses
* either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
+ * RFC_5114 is also handled here for param_nid = (1..3)
*/
if (dctx->param_nid != NID_undef) {
+ int type = dctx->param_nid <= 3 ? EVP_PKEY_DHX : EVP_PKEY_DH;
+
if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
return 0;
- EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh);
- return 1;
- }
-
-#ifndef FIPS_MODULE
- if (dctx->rfc5114_param) {
- switch (dctx->rfc5114_param) {
- case 1:
- dh = DH_get_1024_160();
- break;
-
- case 2:
- dh = DH_get_2048_224();
- break;
-
- case 3:
- dh = DH_get_2048_256();
- break;
-
- default:
- return -2;
- }
- EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
+ EVP_PKEY_assign(pkey, type, dh);
return 1;
}
-#endif /* FIPS_MODULE */
if (ctx->pkey_gencb != NULL) {
pcb = BN_GENCB_new();
diff --git a/crypto/evp/ctrl_params_translate.c b/crypto/evp/ctrl_params_translate.c
index 8f4ffd3bc4..f48e723c33 100644
--- a/crypto/evp/ctrl_params_translate.c
+++ b/crypto/evp/ctrl_params_translate.c
@@ -977,7 +977,7 @@ static int fix_oid(enum state state,
return ret;
}
-/* EVP_PKEY_CTRL_DH_NID, ...??? */
+/* EVP_PKEY_CTRL_DH_NID */
static int fix_dh_nid(enum state state,
const struct translation_st *translation,
struct translation_ctx_st *ctx)
@@ -987,7 +987,7 @@ static int fix_dh_nid(enum state state,
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
- /* This is currently only settable */
+ /* This is only settable */
if (ctx->action_type != SET)
return 0;
@@ -997,16 +997,30 @@ static int fix_dh_nid(enum state state,
ctx->p1 = 0;
}
- if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
+ return default_fixup_args(state, translation, ctx);
+}
+
+/* EVP_PKEY_CTRL_DH_RFC5114 */
+static int fix_dh_nid5114(enum state state,
+ const struct translation_st *translation,
+ struct translation_ctx_st *ctx)
+{
+ int ret;
+
+ if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
- if (state == PRE_PARAMS_TO_CTRL) {
- ctx->p1 =
- ossl_ffc_named_group_get_uid(ossl_ffc_name_to_dh_named_group(ctx->p2));
- ctx->p2 = NULL;
+ /* This is only settable */
+ if (ctx->action_type != SET)
+ return 0;
+
+ if (state == PRE_CTRL_STR_TO_PARAMS) {
+ ctx->p2 = (char *)ossl_ffc_named_group_get_name
+ (ossl_ffc_uid_to_dh_named_group(atoi(ctx->p2)));
+ ctx->p1 = 0;
}
- return ret;
+ return default_fixup_args(state, translation, ctx);
}
/* EVP_PKEY_CTRL_DH_PARAMGEN_TYPE */
@@ -1019,24 +1033,16 @@ static int fix_dh_paramgen_type(enum state state,
if ((ret = default_check(state, translation, ctx)) <= 0)
return ret;
- /* This is currently only settable */
+ /* This is only settable */
if (ctx->action_type != SET)
return 0;
- if (state == PRE_CTRL_TO_PARAMS) {
- ctx->p2 = (char *)ossl_dh_gen_type_id2name(ctx->p1);
- ctx->p1 = 0;
- }
-
- if ((ret = default_fixup_args(state, translation, ctx)) <= 0)
- return ret;
-
- if (state == PRE_PARAMS_TO_CTRL) {
- ctx->p1 = ossl_dh_gen_type_name2id(ctx->p2);
- ctx->p2 = NULL;
+ if (state == PRE_CTRL_STR_TO_PARAMS) {
+ ctx->p2 = (char *)ossl_dh_gen_type_id2name(atoi(ctx->p2));
+ ctx->p1 = strlen(ctx->p2);
}
- return ret;
+ return default_fixup_args(state, translation, ctx);
}
/* EVP_PKEY_CTRL_EC_PARAM_ENC */
@@ -1927,35 +1933,47 @@ static const struct translation_st evp_pkey_ctx_translations[] = {
EVP_PKEY_CTRL_GET_DH_KDF_OID, NULL, NULL,
OSSL_KDF_PARAM_CEK_ALG, OSSL_PARAM_UTF8_STRING, fix_oid },
- { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_DERIVE,
- EVP_PKEY_CTRL_DH_PAD, "dh_pad", NULL,
- OSSL_EXCHANGE_PARAM_PAD, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ /* DHX Keygen Parameters that are shared with DH */
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, "dh_paramgen_type", NULL,
+ OSSL_PKEY_PARAM_FFC_TYPE, OSSL_PARAM_UTF8_STRING, fix_dh_paramgen_type },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, "dh_paramgen_prime_len", NULL,
+ OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_NID, "dh_param", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, NULL },
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_RFC5114, "dh_rfc5114", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid5114 },
+ /* DH Keygen Parameters that are shared with DHX */
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, "dh_paramgen_type", NULL,
+ OSSL_PKEY_PARAM_FFC_TYPE, OSSL_PARAM_UTF8_STRING, fix_dh_paramgen_type },
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, "dh_paramgen_prime_len", NULL,
+ OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_DH_NID, "dh_param", NULL,
OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid },
- { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
- EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN, NULL, NULL,
- OSSL_PKEY_PARAM_FFC_PBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
- { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
- EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, "dh_paramgen_subprime_len", NULL,
- OSSL_PKEY_PARAM_FFC_QBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN,
+ EVP_PKEY_CTRL_DH_RFC5114, "dh_rfc5114", NULL,
+ OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_UTF8_STRING, fix_dh_nid5114 },
+
+ /* DH specific Keygen Parameters */
{ SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR, "dh_paramgen_generator", NULL,
OSSL_PKEY_PARAM_DH_GENERATOR, OSSL_PARAM_INTEGER, NULL },
- { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
- EVP_PKEY_CTRL_DH_PARAMGEN_TYPE, "dh_paramgen_type", NULL,
- OSSL_PKEY_PARAM_FFC_TYPE, OSSL_PARAM_UTF8_STRING, fix_dh_paramgen_type },
- /*
- * This is know to be incorrect, will be fixed and enabled when the
- * underlying code is corrected.
- * Until then, we simply don't support it here.
- */
-#if 0
- { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_PARAMGEN,
- EVP_PKEY_CTRL_DH_RFC5114, "dh_rfc5114", NULL,
- OSSL_PKEY_PARAM_GROUP_NAME, OSSL_PARAM_INTEGER, NULL },
-#endif
+
+ /* DHX specific Keygen Parameters */
+ { SET, EVP_PKEY_DHX, 0, EVP_PKEY_OP_PARAMGEN,
+ EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN, "dh_paramgen_subprime_len", NULL,
+ OSSL_PKEY_PARAM_FFC_QBITS, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
+
+ { SET, EVP_PKEY_DH, 0, EVP_PKEY_OP_DERIVE,
+ EVP_PKEY_CTRL_DH_PAD, "dh_pad", NULL,
+ OSSL_EXCHANGE_PARAM_PAD, OSSL_PARAM_UNSIGNED_INTEGER, NULL },
/*-
* DSA
diff --git a/crypto/evp/dh_support.c b/crypto/evp/dh_support.c
index 7e0256bd00..87296ffbee 100644
--- a/crypto/evp/dh_support.c
+++ b/crypto/evp/dh_support.c
@@ -15,14 +15,25 @@
typedef struct dh_name2id_st{
const char *name;
int id;
+ int type;
} DH_GENTYPE_NAME2ID;
-static const DH_GENTYPE_NAME2ID dhtype2id[]=
+/* Indicates that the paramgen_type can be used for either DH or DHX */
+#define TYPE_ANY -1
+#ifndef OPENSSL_NO_DH
+# define TYPE_DH DH_FLAG_TYPE_DH
+# define TYPE_DHX DH_FLAG_TYPE_DHX
+#else
+# define TYPE_DH 0
+# define TYPE_DHX 0
+#endif
+
+static const DH_GENTYPE_NAME2ID dhtype2id[] =
{
- { "fips186_4", DH_PARAMGEN_TYPE_FIPS_186_4 },
- { "fips186_2", DH_PARAMGEN_TYPE_FIPS_186_2 },
- { "group", DH_PARAMGEN_TYPE_GROUP },
- { "generator", DH_PARAMGEN_TYPE_GENERATOR }
+ { "group", DH_PARAMGEN_TYPE_GROUP, TYPE_ANY },
+ { "generator", DH_PARAMGEN_TYPE_GENERATOR, TYPE_DH },
+ { "fips186_4", DH_PARAMGEN_TYPE_FIPS_186_4, TYPE_DHX },
+ { "fips186_2", DH_PARAMGEN_TYPE_FIPS_186_2, TYPE_DHX },
};
const char *ossl_dh_gen_type_id2name(int id)
@@ -36,13 +47,17 @@ const char *ossl_dh_gen_type_id2name(int id)
return NULL;
}
-int ossl_dh_gen_type_name2id(const char *name)
+#ifndef OPENSSL_NO_DH
+int ossl_dh_gen_type_name2id(const char *name, int type)
{
size_t i;
for (i = 0; i < OSSL_NELEM(dhtype2id); ++i) {
- if (strcmp(dhtype2id[i].name, name) == 0)
+ if ((dhtype2id[i].type == TYPE_ANY
+ || type == dhtype2id[i].type)
+ && strcmp(dhtype2id[i].name, name) == 0)
return dhtype2id[i].id;
}
return -1;
}
+#endif
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index daa0f617d8..3af7e17bee 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -890,13 +890,38 @@ IMPLEMENT_ECX_VARIANT(ED448)
# if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
-int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
+int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *dhkey)
{
- int type = DH_get0_q(key) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
- int ret = EVP_PKEY_assign(pkey, type, key);
+ int ret, type;
+
+ /*
+ * ossl_dh_is_named_safe_prime_group() returns 1 for named safe prime groups
+ * related to ffdhe and modp (which cache q = (p - 1) / 2),
+ * and returns 0 for all other dh parameter generation types including
+ * RFC5114 named groups.
+ *
+ * The EVP_PKEY_DH type is used for dh parameter generation types:
+ * - named safe prime groups related to ffdhe and modp
+ * - safe prime generator
+ *
+ * The type EVP_PKEY_DHX is used for dh parameter generation types
+ * - fips186-4 and fips186-2
+ * - rfc5114 named groups.
+ *
+ * The EVP_PKEY_DH type is used to save PKCS#3 data than can be stored
+ * without a q value.
+ * The EVP_PKEY_DHX type is used to save X9.42 data that requires the
+ * q value to be stored.
+ */
+ if (ossl_dh_is_named_safe_prime_group(dhkey))
+ type = EVP_PKEY_DH;
+ else
+ type = DH_get0_q(dhkey) == NULL ? EVP_PKEY_DH : EVP_PKEY_DHX;
+
+ ret = EVP_PKEY_assign(pkey, type, dhkey);
if (ret)
- DH_up_ref(key);
+ DH_up_ref(dhkey);
return ret;
}
diff --git a/crypto/ffc/ffc_dh.c b/crypto/ffc/ffc_dh.c
index 17888e9291..e9f597c46c 100644
--- a/crypto/ffc/ffc_dh.c
+++ b/crypto/ffc/ffc_dh.c
@@ -113,9 +113,7 @@ const DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p,
if (BN_cmp(p, dh_named_groups[i].p) == 0
&& BN_cmp(g, dh_named_groups[i].g) == 0
/* Verify q is correct if it exists */
- && ((q != NULL && BN_cmp(q, dh_named_groups[i].q) == 0)
- /* Do not match RFC 5114 groups without q */
- || (q == NULL && dh_named_groups[i].uid > 3)))
+ && (q == NULL || BN_cmp(q, dh_named_groups[i].q) == 0))
return &dh_named_groups[i];
}
return NULL;
diff --git a/doc/man1/openssl-genpkey.pod.in b/doc/man1/openssl-genpkey.pod.in
index 7f4ebef439..aa08b01f4f 100644
--- a/doc/man1/openssl-genpkey.pod.in
+++ b/doc/man1/openssl-genpkey.pod.in
@@ -63,7 +63,7 @@ name accepted by EVP_get_cipherbyname() is acceptable such as B<des3>.
=item B<-algorithm> I<alg>
-Public key algorithm to use such as RSA, DSA or DH. If used this option must
+Public key algorithm to use such as RSA, DSA, DH or DHX. If used this option must
precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm>
are mutually exclusive. Engines may add algorithms in addition to the standard
built-in ones.
@@ -74,11 +74,8 @@ X25519, X448, ED25519 and ED448.
Valid built-in algorithm names for parameter generation (see the B<-genparam>
option) are DH, DSA and EC.
-Note that the algorithm name X9.42 DH may be used as a synonym for the DH
-algorithm. These are identical and do not indicate the type of parameters that
-will be generated. Use the B<dh_paramgen_type> option to indicate whether PKCS#3
-or X9.42 DH parameters are required. See L</DH Parameter Generation Options>
-below for more details.
+Note that the algorithm name X9.42 DH may be used as a synonym for DHX keys and
+PKCS#3 refers to DH Keys. Some options are not shared between DH and DHX keys.
=item B<-pkeyopt> I<opt>:I<value>
@@ -182,6 +179,18 @@ B<named_curve> or B<explicit>. The default value is B<named_curve>.
=back
+=head2 DH Key Generation Options
+
+=over 4
+
+=item B<group>:I<name>
+
+The B<paramfile> option is not required if a named group is used here.
+See the L</DH Parameter Generation Options> section below.
+
+=back
+
+
=head1 PARAMETER GENERATION OPTIONS
The options supported by each algorithm and indeed each implementation of an
@@ -214,7 +223,6 @@ ignored. If not set, then a digest will be used that gives an output matching
the number of bits in B<q>, i.e. B<sha1> if q length is 160, B<sha224> if it 224
or B<sha256> if it is 256.
-
=item B<properties>:I<query>
The I<digest> property I<query> string to use when fetching a digest from a provider.
@@ -243,36 +251,128 @@ generate valid primes.
=head2 DH Parameter Generation Options
+For most use cases it is recommended to use the B<group> option rather than
+the B<type> options. Note that the B<group> option is not used by default if
+no parameter generation options are specified.
+
=over 4
+=item B<group>:I<name>
+
+=item B<dh_param>:I<name>
+
+Use a named DH group to select constant values for the DH parameters.
+All other options will be ignored if this value is set.
+
+Valid values that are associated with the B<algorithm> of B<"DH"> are:
+"ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192",
+"modp_1536", "modp_2048", "modp_3072", "modp_4096", "modp_6144", "modp_8192".
+
+Valid values that are associated with the B<algorithm> of B<"DHX"> are the
+RFC5114 names "dh_1024_160", "dh_2048_224", "dh_2048_256".
+
+=item B<dh_rfc5114>:I<num>
+
+If this option is set, then the appropriate RFC5114 parameters are used
+instead of generating new parameters. The value I<num> can be one of
+1, 2 or 3 that are equivalant to using the option B<group> with one of
+"dh_1024_160", "dh_2048_224" or "dh_2048_256".
+All other options will be ignored if this value is set.
+
+=item B<pbits>:I<numbits>
+
=item B<dh_paramgen_prime_len>:I<numbits>
The number of bits in the prime parameter I<p>. The default is 2048.
+=item B<qbits>:I<numbits>
+
=item B<dh_paramgen_subprime_len>:I<numbits>
-The number of bits in the sub prime parameter I<q>. The default is 256 if the
-prime is at least 2048 bits long or 160 otherwise. Only relevant if used in
-conjunction with the B<dh_paramgen_type> option to generate X9.42 DH parameters.
+The number of bits in the sub prime parameter I<q>. The default is 224.
+Only relevant if used in conjunction with the B<dh_paramgen_type> option to
+generate DHX parameters.
+
+=item B<safeprime-generator>:I<value>
=item B<dh_paramgen_generator>:I<value>
The value to use for the generator I<g>. The default is 2.
+The B<algorithm> option must be B<"DH"> for this parameter to be used.
+
+=item B<type>:I<string>
+
+The type name of DH parameters to generate. Valid values are:
+
+=over 4
+
+=item "generator"
+
+Use a safe prime generator with the option B<safeprime_generator>
+The B<algorithm> option must be B<"DH">.
+
+=item "fips186_4"
+
+FIPS186-4 parameter generation.
+The B<algorithm> option must be B<"DHX">.
+
+=item "fips186_2"
+
+FIPS186-4 parameter generation.
+The B<algorithm> option must be B<"DHX">.
+
+=item "group"
+
+Can be used with the option B<pbits> to select one of
+"ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144" or "ffdhe8192".
+The B<algorithm> option must be B<"DH">.
+
+=item "default"
+
+Selects a default type based on the B<algorithm>. This is used by the
+OpenSSL default provider to set the type for backwards compatability.
+If B<algorithm> is B<"DH"> then B<"generator"> is used.
+If B<algorithm> is B<"DHX"> then B<"fips186_2"> is used.
+
+=back
=item B<dh_paramgen_type>:I<value>
-The type of DH parameters to generate. Use 0 for PKCS#3 DH and 1 for X9.42 DH.
-The default is 0.
+The type of DH parameters to generate. Valid values are 0, 1, 2 or 3
+which correspond to setting the option B<type> to
+"generator", "fips186_2", "fips186_4" or "group".
-=item B<dh_rfc5114>:I<num>
+=item B<digest>:I<digest>
-If this option is set, then the appropriate RFC5114 parameters are used
-instead of generating new parameters. The value I<num> can be one of
-1, 2 or 3 corresponding to RFC5114 DH parameters consisting of
-1024 bit group with 160 bit subgroup, 2048 bit group with 224 bit subgroup
-and 2048 bit group with 256 bit subgroup as mentioned in RFC5114 sections
-2.1, 2.2 and 2.3 respectively. If present this overrides all other DH parameter
-options.
+The digest to use during parameter generation. Must be one of B<sha1>, B<sha224>
+or B<sha256>. If set, then the number of bits in B<qbits> will match the output
+size of the specified digest and the B<qbits> parameter will be
+ignored. If not set, then a digest will be used that gives an output matching
+the number of bits in B<q>, i.e. B<sha1> if q length is 160, B<sha224> if it is
+224 or B<sha256> if it is 256.
+This is only used by "fips186_4" and "fips186_2" key generation.
+
+=item B<properties>:I<query>
+
+The I<digest> property I<query> string to use when fetching a digest from a provider.
+This is only used by "fips186_4" and "fips186_2" key generation.
+
+=item B<gindex>:I<index>
+
+The index to use for canonical generation and verification of the generator g.
+Set this to a positive value ranging from 0..255 to use this mode. Larger values
+will only use the bottom byte.
+This I<index> must then be reused during key validation to verify the value of g.
+If this value is not set then g is not verifiable. The default value is -1.
+This is only used by "fips186_4" and "fips186_2" key generation.
+
+=item B<hexseed>:I<seed>
+
+The seed I<seed> data to use instead of generating a random seed internally.
+This should be used for testing purposes only. This will either produced fixed
+values for the generated parameters OR it will fail if the seed did not
+generate valid primes.
+This is only used by "fips186_4" and "fips186_2" key generation.
=back
@@ -313,25 +413,49 @@ Generate DSA key from parameters:
openssl genpkey -paramfile dsap.pem -out dsakey.pem
-Generate 2048 bit DH parameters:
+Generate 4096 bit DH Key using safe prime group ffdhe4096:
+
+ openssl genpkey -algorithm DH -out dhkey.pem -pkeyopt group:ffdhe4096
+
+Generate 2048 bit X9.42 DH key with 256 bit subgroup using RFC5114 group3:
+
+ openssl genpkey -algorithm DHX -out dhkey.pem -pkeyopt dh_rfc5114:3
+
+Generate a DH key using a DH parameters file:
+
+ openssl genpkey -paramfile dhp.pem -out dhkey.pem
+
+Output DH parameters for safe prime group ffdhe2048:
+
+ openssl genpkey -genparam -algorithm DH -out dhp.pem -pkeyopt group:ffdhe2048
+
+Output 2048 bit X9.42 DH parameters with 224 bit subgroup using RFC5114 group2:
+
+ openssl genpkey -genparam -algorithm DHX -out dhp.pem -pkeyopt dh_rfc5114:2
+
+Output 2048 bit X9.42 DH parameters with 224 bit subgroup using FIP186-4 keygen:
+
+ openssl genpkey -genparam -algorithm DHX -out dhp.pem -text \
+ -pkeyopt pbits:2048 -pkeyopt qbits:224 -pkeyopt digest:SHA256 \
+ -pkeyopt gindex:1 -pkeyopt dh_paramgen_type:2
+
+Output 1024 bit X9.42 DH parameters with 160 bit subgroup using FIP186-2 keygen:
+
+ openssl genpkey -genparam -algorithm DHX -out dhp.pem -text \
+ -pkeyopt pbits:1024 -pkeyopt qbits:160 -pkeyopt digest:SHA1 \
+ -pkeyopt gindex:1 -pkeyopt dh_paramgen_type:1
+
+Output 2048 bit DH parameters:
openssl genpkey -genparam -algorithm DH -out dhp.pem \
-pkeyopt dh_paramgen_prime_len:2048
-Generate 2048 bit X9.42 DH parameters:
+Output 2048 bit DH parameters using a generator:
openssl genpkey -genparam -algorithm DH -out dhpx.pem \
-pkeyopt dh_paramgen_prime_len:2048 \
-pkeyopt dh_paramgen_type:1
-Output RFC5114 2048 bit DH parameters with 224 bit subgroup:
-
- openssl genpkey -genparam -algorithm DH -out dhp.pem -pkeyopt dh_rfc5114:2
-
-Generate DH key from parameters:
-
- openssl genpkey -paramfile dhp.pem -out dhkey.pem
-
Generate EC parameters:
openssl genpkey -genparam -algorithm EC -out ecp.pem \
@@ -367,7 +491,7 @@ The B<-engine> option was deprecated in OpenSSL 3.0.
=head1 COPYRIGHT
-Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
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
diff --git a/doc/man7/EVP_PKEY-DH.pod b/doc/man7/EVP_PKEY-DH.pod
index 72d20f6f1c..60865a7120 100644
--- a/doc/man7/EVP_PKEY-DH.pod
+++ b/doc/man7/EVP_PKEY-DH.pod
@@ -2,7 +2,8 @@
=head1 NAME
-EVP_PKEY-DH, EVP_KEYMGMT-DH - EVP_PKEY DH keytype and algorithm support
+EVP_PKEY-DH, EVP_PKEY-DHX, EVP_KEYMGMT-DH
+- EVP_PKEY DH and DHX keytype and algorithm support
=head1 DESCRIPTION
@@ -14,25 +15,30 @@ applications that cannot be upgraded to use the approved safe-prime groups.
See L<EVP_PKEY-FFC(7)> for more information about FFC keys.
-For B<DH> that is not a named group the FIPS186-4 standard specifies that the
+The B<DH> key type uses PKCS#3 format which saves p and g, but not the 'q' value.
+The B<DHX> key type uses X9.42 format which saves the value of 'q' and this
+must be used for FIPS186-4.
+
+For B<DHX> that is not a named group the FIPS186-4 standard specifies that the
values used for FFC parameter generation are also required for parameter
validation. This means that optional FFC domain parameter values for
-I<seed>, I<pcounter> and I<gindex> may need to be stored for validation purposes.
-For B<DH> the I<seed> and I<pcounter> can be stored in ASN1 data
-(but the I<gindex> is not).
+I<seed>, I<pcounter> and I<gindex> or I<hindex> may need to be stored for
+validation purposes.
+For B<DHX> the I<seed> and I<pcounter> can be stored in ASN1 data
+(but the I<gindex> or I<hindex> can not be stored).
-=head2 DH parameters
+=head2 DH and DHX domain parameters
In addition to the common FCC parameters that all FFC keytypes should support
-(see L<EVP_PKEY-FFC(7)/FFC parameters>) the B<DH> keytype
-implementation supports the following:
+(see L<EVP_PKEY-FFC(7)/FFC parameters>) the B<DHX> and B<DH> keytype
+implementations support the following:
=over 4
=item "group" (B<OSSL_PKEY_PARAM_GROUP_NAME>) <UTF8 string>
-Set or gets a string that associates a B<DH> named safe prime group with known
-values for I<p>, I<q> and I<g>.
+Sets or gets a string that associates a B<DH> or B<DHX> named safe prime group
+with known values for I<p>, I<q> and I<g>.
The following values can be used by the OpenSSL's default and FIPS providers:
"ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192",
@@ -41,31 +47,46 @@ The following values can be used by the OpenSSL's default and FIPS providers:
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 named groups can be easily validated since the parameters are well known.
+DH/DHX named groups can be easily validated since the parameters are well known.
For protocols that only transfer I<p> and I<g> the value of I<q> can also be
retrieved.
-=item "safeprime-generator" (B<OSSL_PKEY_PARAM_DH_GENERATOR>) <integer>
+=back
-Used for DH generation of safe primes using the old generator code.
-It is recommended to use a named safe prime group instead, if domain parameter
-validation is required. The default value is 2.
+=head2 DH and DHX additional parameters
-These are not named safe prime groups so setting this value for the OpenSSL FIPS
-provider will instead choose a named safe prime group based on the size of I<p>.
+=over 4
=item "encoded-pub-key" (B<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
Used for getting and setting the encoding of the DH public key used in a key
exchange message for the TLS protocol.
+See EVP_PKEY_set1_encoded_public_key() and EVP_PKEY_get1_encoded_public_key().
+
+=back
+
+=head2 DH additional domain parameters
+
+=over 4
+
+=item "safeprime-generator" (B<OSSL_PKEY_PARAM_DH_GENERATOR>) <integer>
+
+Used for DH generation of safe primes using the old safe prime generator code.
+The default value is 2.
+It is recommended to use a named safe prime group instead, if domain parameter
+validation is required.
+
+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 I<p>.
=back
-=head2 DH domain parameter / key generation parameters
+=head2 DH and DHX domain parameter / key generation parameters
In addition to the common FFC key generation parameters that all FFC key types
should support (see L<EVP_PKEY-FFC(7)/FFC key generation parameters>) the
-B<DH> keytype implementation supports the following:
+B<DH> and B<DHX> keytype implementation supports the following:
=over 4
@@ -91,6 +112,7 @@ type.
=item "generator"
A safe prime generator. See the "safeprime-generator" type above.
+This is only valid for B<DH> keys.
=back
diff --git a/doc/man7/EVP_PKEY-FFC.pod b/doc/man7/EVP_PKEY-FFC.pod
index 7e238d7b44..e345580ec1 100644
--- a/doc/man7/EVP_PKEY-FFC.pod
+++ b/doc/man7/EVP_PKEY-FFC.pod
@@ -2,7 +2,7 @@
=head1 NAME
-EVP_PKEY-FFC - EVP_PKEY DSA and DH shared FFC parameters.
+EVP_PKEY-FFC - EVP_PKEY DSA and DH/DHX shared FFC parameters.
=head1 DESCRIPTION
@@ -11,9 +11,9 @@ cryptography using finite field mathematics. DSA is an example of FFC and
Diffie-Hellman key establishment algorithms specified in SP800-56A can also be
implemented as FFC.
-The B<DSA> and B<DH> keytypes are implemented in OpenSSL's default and FIPS
-providers.
-The implementations support the basic DSA and DH keys, containing the public
+The B<DSA>, B<DH> and B<DHX> keytypes are implemented in OpenSSL's default and
+FIPS providers.
+The implementations support the basic DSA, DH and DHX keys, containing the public
and private keys I<pub> and I<priv> as well as the three main domain parameters
I<p>, I<q> and I<g>.
@@ -26,10 +26,14 @@ For B<DH> the I<seed> and I<pcounter> can be stored in ASN1 data
(but the I<gindex> is not). For B<DSA> however, these fields are not stored in
the ASN1 data so they need to be stored externally if validation is required.
+The B<DH> key type uses PKCS#3 format which saves p and g, but not the 'q' value.
+The B<DHX> key type uses X9.42 format which saves the value of 'q' and this
+must be used for FIPS186-4.
+
=head2 FFC parameters
In addi