static DH * dh_generate(int size, int gen) { struct ossl_generate_cb_arg cb_arg = { 0 }; struct dh_blocking_gen_arg gen_arg; DH *dh = DH_new(); BN_GENCB *cb = BN_GENCB_new(); if (!dh || !cb) { DH_free(dh); BN_GENCB_free(cb); return NULL; } if (rb_block_given_p()) cb_arg.yield = 1; BN_GENCB_set(cb, ossl_generate_cb_2, &cb_arg); gen_arg.dh = dh; gen_arg.size = size; gen_arg.gen = gen; gen_arg.cb = cb; if (cb_arg.yield == 1) { /* we cannot release GVL when callback proc is supplied */ dh_blocking_gen(&gen_arg); } else { /* there's a chance to unblock */ rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); } BN_GENCB_free(cb); if (!gen_arg.result) { DH_free(dh); if (cb_arg.state) { /* Clear OpenSSL error queue before re-raising. */ ossl_clear_error(); rb_jump_tag(cb_arg.state); } return NULL; } if (!DH_generate_key(dh)) { DH_free(dh); return NULL; } return dh; }
static DH * dh_generate(int size, int gen) { #if defined(HAVE_DH_GENERATE_PARAMETERS_EX) && HAVE_BN_GENCB BN_GENCB cb; struct ossl_generate_cb_arg cb_arg; struct dh_blocking_gen_arg gen_arg; DH *dh = DH_new(); if (!dh) return 0; memset(&cb_arg, 0, sizeof(struct ossl_generate_cb_arg)); if (rb_block_given_p()) cb_arg.yield = 1; BN_GENCB_set(&cb, ossl_generate_cb_2, &cb_arg); gen_arg.dh = dh; gen_arg.size = size; gen_arg.gen = gen; gen_arg.cb = &cb; if (cb_arg.yield == 1) { /* we cannot release GVL when callback proc is supplied */ dh_blocking_gen(&gen_arg); } else { /* there's a chance to unblock */ rb_thread_call_without_gvl(dh_blocking_gen, &gen_arg, ossl_generate_cb_stop, &cb_arg); } if (!gen_arg.result) { DH_free(dh); if (cb_arg.state) rb_jump_tag(cb_arg.state); return 0; } #else DH *dh; dh = DH_generate_parameters(size, gen, rb_block_given_p() ? ossl_generate_cb : NULL, NULL); if (!dh) return 0; #endif if (!DH_generate_key(dh)) { DH_free(dh); return 0; } return dh; }