- const char *type, const char *value)
- {
- if (!strcmp(type, "dh_paramgen_prime_len"))
- {
- int len;
- len = atoi(value);
- return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
- }
- if (!strcmp(type, "dh_paramgen_generator"))
- {
- int len;
- len = atoi(value);
- return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
- }
- return -2;
- }
-
-static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
- {
- DH *dh = NULL;
- DH_PKEY_CTX *dctx = ctx->data;
- BN_GENCB *pcb, cb;
- int ret;
- if (ctx->pkey_gencb)
- {
- pcb = &cb;
- evp_pkey_set_cb_translate(pcb, ctx);
- }
- else
- pcb = NULL;
- dh = DH_new();
- if (!dh)
- return 0;
- ret = DH_generate_parameters_ex(dh,
- dctx->prime_len, dctx->generator, pcb);
- if (ret)
- EVP_PKEY_assign_DH(pkey, dh);
- else
- DH_free(dh);
- return ret;
- }
+ const char *type, const char *value)
+{
+ if (strcmp(type, "dh_paramgen_prime_len") == 0) {
+ int len;
+ len = atoi(value);
+ return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
+ }
+ if (strcmp(type, "dh_rfc5114") == 0) {
+ DH_PKEY_CTX *dctx = ctx->data;
+ int id;
+
+ id = atoi(value);
+ if (id < 0 || id > 3)
+ return -2;
+ dctx->param_nid = id;
+ return 1;
+ }
+ if (strcmp(type, "dh_param") == 0) {
+ DH_PKEY_CTX *dctx = ctx->data;
+ int nid = OBJ_sn2nid(value);
+
+ if (nid == NID_undef) {
+ ERR_raise(ERR_LIB_DH, DH_R_INVALID_PARAMETER_NAME);
+ return -2;
+ }
+ dctx->param_nid = nid;
+ return 1;
+ }
+ if (strcmp(type, "dh_paramgen_generator") == 0) {
+ int len;
+ len = atoi(value);
+ return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
+ }
+ if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
+ int len;
+ len = atoi(value);
+ return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
+ }
+ if (strcmp(type, "dh_paramgen_type") == 0) {
+ int typ;
+ typ = atoi(value);
+ return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
+ }
+ if (strcmp(type, "dh_pad") == 0) {
+ int pad;
+ pad = atoi(value);
+ return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
+ }
+ return -2;
+}
+
+static DH *ffc_params_generate(OSSL_LIB_CTX *libctx, DH_PKEY_CTX *dctx,
+ BN_GENCB *pcb)
+{
+ DH *ret;
+ int rv = 0;
+ int res;
+ int prime_len = dctx->prime_len;
+ int subprime_len = dctx->subprime_len;
+
+ if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
+ return NULL;
+ ret = DH_new();
+ if (ret == NULL)
+ return NULL;
+
+ if (subprime_len == -1) {
+ if (prime_len >= 2048)
+ subprime_len = 256;
+ else
+ subprime_len = 160;
+ }
+
+ if (dctx->md != NULL)
+ ossl_ffc_set_digest(&ret->params, EVP_MD_get0_name(dctx->md), NULL);
+
+# ifndef FIPS_MODULE
+ if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
+ rv = ossl_ffc_params_FIPS186_2_generate(libctx, &ret->params,
+ FFC_PARAM_TYPE_DH,
+ prime_len, subprime_len, &res,
+ pcb);
+ else
+# endif
+ /* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
+ if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
+ rv = ossl_ffc_params_FIPS186_4_generate(libctx, &ret->params,
+ FFC_PARAM_TYPE_DH,
+ prime_len, subprime_len, &res,
+ pcb);
+ if (rv <= 0) {
+ DH_free(ret);
+ return NULL;
+ }
+ return ret;
+}
+
+static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx,
+ EVP_PKEY *pkey)
+{
+ DH *dh = NULL;
+ DH_PKEY_CTX *dctx = ctx->data;
+ BN_GENCB *pcb = NULL;
+ int ret;
+
+ /*
+ * 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, type, dh);
+ return 1;
+ }
+
+ if (ctx->pkey_gencb != NULL) {
+ pcb = BN_GENCB_new();
+ if (pcb == NULL)
+ return 0;
+ evp_pkey_set_cb_translate(pcb, ctx);
+ }
+# ifdef FIPS_MODULE
+ dctx->paramgen_type = DH_PARAMGEN_TYPE_FIPS_186_4;
+# endif /* FIPS_MODULE */
+ if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2) {
+ dh = ffc_params_generate(NULL, dctx, pcb);
+ BN_GENCB_free(pcb);
+ if (dh == NULL)
+ return 0;
+ EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
+ return 1;
+ }
+ dh = DH_new();
+ if (dh == NULL) {
+ BN_GENCB_free(pcb);
+ return 0;
+ }
+ ret = DH_generate_parameters_ex(dh,
+ dctx->prime_len, dctx->generator, pcb);
+ BN_GENCB_free(pcb);
+ if (ret)
+ EVP_PKEY_assign_DH(pkey, dh);
+ else
+ DH_free(dh);
+ return ret;
+}