+
+ for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) {
+ if (strcasecmp(dh_named_groups[i].name, name) == 0) {
+ int max_target_security_strength =
+ ifc_ffc_compute_security_bits(dh_named_groups[i].nbits);
+
+ /*
+ * The last parameter specified here is
+ * 2 * max_target_security_strength.
+ * See SP800-56Ar3 Table(s) 25 & 26.
+ */
+ return dh_param_init(libctx, dh_named_groups[i].uid,
+ dh_named_groups[i].p,
+ dh_named_groups[i].q,
+ dh_named_groups[i].g,
+ 2 * max_target_security_strength);
+ }
+ }
+ DHerr(0, DH_R_INVALID_PARAMETER_NID);
+ return NULL;
+}
+
+DH *dh_new_by_nid_with_libctx(OPENSSL_CTX *libctx, int nid)
+{
+ const char *name = ffc_named_group_from_uid(nid);
+
+ return dh_new_by_group_name(libctx, name);
+}
+
+DH *DH_new_by_nid(int nid)
+{
+ return dh_new_by_nid_with_libctx(NULL, nid);
+}
+
+int ffc_set_group_pqg(FFC_PARAMS *ffc, const char *group_name)
+{
+ int i;
+ BIGNUM *q = NULL;
+
+ if (ffc == NULL)
+ return 0;
+
+ for (i = 0; i < (int)OSSL_NELEM(dh_named_groups); ++i) {
+ if (strcasecmp(dh_named_groups[i].name, group_name) == 0) {
+ if (dh_named_groups[i].q != NULL) {
+ /* For groups with a q */
+ ffc_params_set0_pqg(ffc,
+ (BIGNUM *)dh_named_groups[i].p,
+ (BIGNUM *)dh_named_groups[i].q,
+ (BIGNUM *)dh_named_groups[i].g);
+ } else {
+ /* For SAFE PRIME GROUPS */
+ /* Set q = (p - 1) / 2 (p is known to be odd so just shift right) */
+ q = BN_dup(dh_named_groups[i].p);
+ if (q == NULL || !BN_rshift1(q, q))
+ break; /* exit with failure */
+
+ ffc_params_set0_pqg(ffc,
+ (BIGNUM *)dh_named_groups[i].p, q,
+ (BIGNUM *)dh_named_groups[i].g);
+ }
+ /* flush the cached nid, The DH layer is responsible for caching */
+ ffc->nid = NID_undef;
+ return 1;
+ }