diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index c3e03c7..fb21bc2 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -29,6 +29,7 @@ typedef struct {
     /* message digest used for parameter generation */
     const EVP_MD *md;
     int rfc5114_param;
+  int param_nid;
     /* Keygen callback info */
     int gentmp[2];
     /* KDF (if any) to use for DH */
@@ -55,7 +56,7 @@ static int pkey_dh_init(EVP_PKEY_CTX *ctx)
     dctx->subprime_len = -1;
     dctx->generator = 2;
     dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
-
+    dctx->param_nid = NID_undef;
     ctx->data = dctx;
     ctx->keygen_info = dctx->gentmp;
     ctx->keygen_info_count = 2;
@@ -87,6 +88,7 @@ static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
     dctx->use_dsa = sctx->use_dsa;
     dctx->md = sctx->md;
     dctx->rfc5114_param = sctx->rfc5114_param;
+    dctx->param_nid = sctx->param_nid;
 
     dctx->kdf_type = sctx->kdf_type;
     dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
@@ -137,11 +139,17 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
         return 1;
 
     case EVP_PKEY_CTRL_DH_RFC5114:
-        if (p1 < 1 || p1 > 3)
+        if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
             return -2;
         dctx->rfc5114_param = p1;
         return 1;
 
+    case EVP_PKEY_CTRL_DH_NID:
+        if (p1 <= 0 || dctx->rfc5114_param != 0)
+            return -2;
+        dctx->param_nid = p1;
+        return 1;
+
     case EVP_PKEY_CTRL_PEER_KEY:
         /* Default behaviour is OK */
         return 1;
@@ -212,6 +220,16 @@ static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
         len = atoi(value);
         return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
     }
+    if (strcmp(type, "dh_param") == 0) {
+        DH_PKEY_CTX *dctx = ctx->data;
+        int nid = OBJ_sn2nid(value);
+
+        if (nid == NID_undef) {
+            return -2;
+        }
+        dctx->param_nid = nid;
+        return 1;
+    }
     if (strcmp(type, "dh_rfc5114") == 0) {
         DH_PKEY_CTX *dctx = ctx->data;
         int len;
@@ -320,6 +338,53 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
         return 1;
     }
 
+     /*
+     * Look for a safe prime group for key establishment. Which uses
+     * either RFC_3526 (modp_XXXX) or RFC_7919 (ffdheXXXX).
+     */
+    if (dctx->param_nid != 0) {
+      switch (dctx->param_nid) {
+      case NID_ffdhe2048:
+        dh = DH_rfc7919_get_2048();
+   break;
+      case NID_ffdhe3072:
+        dh = DH_rfc7919_get_3072();
+   break;
+      case NID_ffdhe4096:
+        dh = DH_rfc7919_get_4096();
+   break;
+      case NID_ffdhe6144:
+        dh = DH_rfc7919_get_6144();
+   break;
+      case NID_ffdhe8192:
+        dh = DH_rfc7919_get_8192();
+   break;
+      case NID_modp_2048:
+        dh = DH_rfc3526_get_2048();
+   break;
+      case NID_modp_3072:
+        dh = DH_rfc3526_get_3072();
+   break;
+      case NID_modp_4096:
+        dh = DH_rfc3526_get_4096();
+   break;
+      case NID_modp_6144:
+        dh = DH_rfc3526_get_6144();
+   break;
+      case NID_modp_8192:
+        dh = DH_rfc3526_get_8192();
+   break;
+      case NID_modp_1536:
+        dh = DH_rfc3526_get_1536();
+   break;
+      default:
+        return NULL;
+      }
+        EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh);
+        return 1;
+    }
+
+
     if (ctx->pkey_gencb) {
         pcb = BN_GENCB_new();
         if (pcb == NULL)
@@ -360,16 +425,22 @@ static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
 {
     DH *dh = NULL;
-    if (ctx->pkey == NULL) {
+    DH_PKEY_CTX *dctx = ctx->data;
+
+    if (ctx->pkey == NULL && dctx->param_nid == 0) {
         DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET);
         return 0;
     }
-    dh = DH_new();
+    if (dctx->param_nid != 0)
+        dh = DH_new_by_nid(dctx->param_nid);
+    else
+        dh = DH_new();
+
     if (dh == NULL)
         return 0;
     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
     /* Note: if error return, pkey is freed by parent routine */
-    if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+    if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
         return 0;
     return DH_generate_key(pkey->pkey.dh);
 }
diff --git a/crypto/dh/dh_rfc5114.c b/crypto/dh/dh_rfc5114.c
index c4a2195..f05d6e5 100644
--- a/crypto/dh/dh_rfc5114.c
+++ b/crypto/dh/dh_rfc5114.c
@@ -36,6 +36,60 @@ DH *DH_get_##x(void) \
     return dh; \
 }
 
+/* Similar macro to make a DH structure for rfc3526 */
+
+#define make_rfc3526_dh(x) \
+DH * DH_rfc3526_get_##x(void) \
+        { \
+        DH *dh; \
+        dh = DH_new(); \
+        if (!dh) \
+                return NULL; \
+        dh->p = BN_dup(&_bignum_modp_##x##_p); \
+        dh->q = BN_dup(&_bignum_modp_##x##_q); \
+        dh->g = BN_dup(&_bignum_const_2); \
+        if (!dh->p || !dh->q || !dh->g) \
+                { \
+                DH_free(dh); \
+                return NULL; \
+                } \
+        return dh; \
+        }
+
+make_rfc3526_dh(1536)
+make_rfc3526_dh(2048)
+make_rfc3526_dh(3072)
+make_rfc3526_dh(4096)
+make_rfc3526_dh(6144)
+make_rfc3526_dh(8192)
+
+
+/* Similar macro to make a DH structure for rfc7919 */
+
+#define make_rfc7919_dh(x) \
+DH * DH_rfc7919_get_##x(void) \
+        { \
+        DH *dh; \
+        dh = DH_new(); \
+        if (!dh) \
+                return NULL; \
+        dh->p = BN_dup(&_bignum_ffdhe##x##_p); \
+        dh->q = BN_dup(&_bignum_ffdhe##x##_q); \
+        dh->g = BN_dup(&_bignum_const_2); \
+        if (!dh->p || !dh->q || !dh->g) \
+                { \
+                DH_free(dh); \
+                return NULL; \
+                } \
+        return dh; \
+        }
+
+make_rfc7919_dh(2048)
+make_rfc7919_dh(3072)
+make_rfc7919_dh(4096)
+make_rfc7919_dh(6144)
+make_rfc7919_dh(8192)
+
 make_dh(1024_160)
 make_dh(2048_224)
 make_dh(2048_256)
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index c1d8e5d..4d33932 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -963,7 +963,7 @@ static const unsigned char so[6765] = {
     0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1C,  /* [ 6753] OBJ_id_ct_xml */
 };
 
-#define NUM_NID 1073
+#define NUM_NID 1131
 static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"UNDEF", "undefined", NID_undef},
     {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
@@ -2032,15 +2032,73 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
     {"modp_3072", "modp_3072", NID_modp_3072},
     {"modp_4096", "modp_4096", NID_modp_4096},
     {"modp_6144", "modp_6144", NID_modp_6144},
-    {"modp_8192", "modp_8192", NID_modp_8192},
-    {"ffdhe2048", "ffdhe2048", NID_ffdhe2048},
+    {"modp_8192", "modp_8192", NID_modp_8192}, /* 1068 */
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef}, /* 1070 */
+    {"UNDEF", "undefined", NID_undef}, 
+    {"UNDEF", "undefined", NID_undef}, /* The original import of openssl-DH assigned   */
+    {"UNDEF", "undefined", NID_undef}, /* the ffdhe groups to 1126-1130.               */
+    {"UNDEF", "undefined", NID_undef}, /* Since that number is hardwired into client   */
+    {"UNDEF", "undefined", NID_undef}, /* code which we support, the fix is to extend  */
+    {"UNDEF", "undefined", NID_undef}, /* the nid_objs array with a gap to accomodate. */
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef}, /* 1080 */
+    {"UNDEF", "undefined", NID_undef}, 
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef}, /* 1090 */
+    {"UNDEF", "undefined", NID_undef}, 
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef}, /* 1100 */
+    {"UNDEF", "undefined", NID_undef}, 
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef}, /* 1110 */
+    {"UNDEF", "undefined", NID_undef}, 
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef}, /* 1120 */
+    {"UNDEF", "undefined", NID_undef}, 
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"UNDEF", "undefined", NID_undef},
+    {"ffdhe2048", "ffdhe2048", NID_ffdhe2048}, /* 1127 */
     {"ffdhe3072", "ffdhe3072", NID_ffdhe3072},
     {"ffdhe4096", "ffdhe4096", NID_ffdhe4096},
     {"ffdhe6144", "ffdhe6144", NID_ffdhe6144},
-    {"ffdhe8192", "ffdhe8192", NID_ffdhe8192},
+    {"ffdhe8192", "ffdhe8192", NID_ffdhe8192}, /*  1131 */
 };
 
-#define NUM_SN 1059
+#define NUM_SN 1064
 static const unsigned int sn_objs[NUM_SN] = {
      364,    /* "AD_DVCS" */
      419,    /* "AES-128-CBC" */
@@ -2422,6 +2480,11 @@ static const unsigned int sn_objs[NUM_SN] = {
      372,    /* "extendedStatus" */
      867,    /* "facsimileTelephoneNumber" */
      462,    /* "favouriteDrink" */
+     1126,   /* "ffdhe2048" */
+     1127,   /* "ffdhe3072" */
+     1128,   /* "ffdhe4096" */
+     1129,   /* "ffdhe6144" */
+     1130,   /* "ffdhe8192" */
      857,    /* "freshestCRL" */
      453,    /* "friendlyCountry" */
      490,    /* "friendlyCountryName" */
@@ -3103,7 +3166,7 @@ static const unsigned int sn_objs[NUM_SN] = {
      160,    /* "x509Crl" */
 };
 
-#define NUM_LN 1059
+#define NUM_LN 1064
 static const unsigned int ln_objs[NUM_LN] = {
      363,    /* "AD Time Stamping" */
      405,    /* "ANSI X9.62" */
@@ -3509,6 +3572,11 @@ static const unsigned int ln_objs[NUM_LN] = {
       56,    /* "extendedCertificateAttributes" */
      867,    /* "facsimileTelephoneNumber" */
      462,    /* "favouriteDrink" */
+     1126,   /* "ffdhe2048" */
+     1127,   /* "ffdhe3072" */
+     1128,   /* "ffdhe4096" */
+     1129,   /* "ffdhe6144" */
+     1130,   /* "ffdhe8192" */
      453,    /* "friendlyCountry" */
      490,    /* "friendlyCountryName" */
      156,    /* "friendlyName" */
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
index 96473ea..713fb66 100644
--- a/crypto/objects/obj_mac.num
+++ b/crypto/objects/obj_mac.num
@@ -1065,3 +1065,8 @@ modp_3072		1064
 modp_4096		1065
 modp_6144		1066
 modp_8192		1067
+ffdhe2048		1126
+ffdhe3072		1127
+ffdhe4096		1128
+ffdhe6144		1129
+ffdhe8192		1130
diff --git a/doc/apps/genpkey.pod b/doc/apps/genpkey.pod
index 91b12e2..b083829 100644
--- a/doc/apps/genpkey.pod
+++ b/doc/apps/genpkey.pod
@@ -195,6 +195,15 @@ The value to use for the generator B<g>. The default is 2.
 The type of DH parameters to generate. Use 0 for PKCS#3 DH and 1 for X9.42 DH.
 The default is 0.
 
+=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 are:
+"ffdhe2048", "ffdhe3072", "ffdhe4096", "ffdhe6144", "ffdhe8192",
+"modp_1536", "modp_2048", "modp_3072", "modp_4096", "modp_6144", "modp_8192".
+
 =item B<dh_rfc5114:num>
 
 If this option is set, then the appropriate RFC5114 parameters are used
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index cb35c05..c35087e 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -162,7 +162,22 @@ DH *DH_get_1024_160(void);
 DH *DH_get_2048_224(void);
 DH *DH_get_2048_256(void);
 
-/* Named parameters, currently RFC7919 */
+/* RFC 5114 parameters */
+DH *DH_rfc7919_get_2048(void);
+DH *DH_rfc7919_get_3072(void);
+DH *DH_rfc7919_get_4096(void);
+DH *DH_rfc7919_get_6144(void);
+DH *DH_rfc7919_get_8192(void);
+
+/* RFC 3526 parameters */
+DH *DH_rfc3526_get_1536(void);
+DH *DH_rfc3526_get_2048(void);
+DH *DH_rfc3526_get_3072(void);
+DH *DH_rfc3526_get_4096(void);
+DH *DH_rfc3526_get_6144(void);
+DH *DH_rfc3526_get_8192(void);
+
+/* Named parameters, currently RFC7919 and RFC3526*/
 DH *DH_new_by_nid(int nid);
 int DH_get_nid(const DH *dh);
 
@@ -306,6 +321,7 @@ int DH_meth_set_generate_params(DH_METHOD *dhm,
 # define EVP_PKEY_CTRL_GET_DH_KDF_UKM            (EVP_PKEY_ALG_CTRL + 12)
 # define EVP_PKEY_CTRL_DH_KDF_OID                (EVP_PKEY_ALG_CTRL + 13)
 # define EVP_PKEY_CTRL_GET_DH_KDF_OID            (EVP_PKEY_ALG_CTRL + 14)
+# define EVP_PKEY_CTRL_DH_NID                    (EVP_PKEY_ALG_CTRL + 15)
 
 /* KDF types */
 # define EVP_PKEY_DH_KDF_NONE                            1
