static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
{
    EVP_PKEY *pkey;
    EC_KEY *ec = NULL;
    VALUE arg, pass;
    VALUE group = Qnil;
    char *passwd = NULL;
    GetPKey(self, pkey);
    if (pkey->pkey.ec)
        ossl_raise(eECError, "EC_KEY already initialized");
    rb_scan_args(argc, argv, "02", &arg, &pass);
    if (NIL_P(arg)) {
        ec = EC_KEY_new();
    } else {
        if (rb_obj_is_kind_of(arg, cEC)) {
            EC_KEY *other_ec = NULL;
            SafeRequire_EC_KEY(arg, other_ec);
            ec = EC_KEY_dup(other_ec);
        } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
                ec = EC_KEY_new();
                group = arg;
        } else {
            BIO *in = ossl_obj2bio(arg);
            if (!NIL_P(pass)) {
                passwd = StringValuePtr(pass);
            }
            ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
            if (!ec) {
                OSSL_BIO_reset(in);
                ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd);
            }
            if (!ec) {
                OSSL_BIO_reset(in);
                ec = d2i_ECPrivateKey_bio(in, NULL);
            }
            if (!ec) {
                OSSL_BIO_reset(in);
                ec = d2i_EC_PUBKEY_bio(in, NULL);
            }
            BIO_free(in);
            if (ec == NULL) {
                const char *name = StringValueCStr(arg);
                int nid = OBJ_sn2nid(name);
                (void)ERR_get_error();
                if (nid == NID_undef)
                    ossl_raise(eECError, "unknown curve name (%s)\n", name);
                if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
                    ossl_raise(eECError, "unable to create curve (%s)\n", name);
                EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
                EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
            }
        }
    }
    if (ec == NULL)
        ossl_raise(eECError, NULL);
    if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
        EC_KEY_free(ec);
        ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
    }
    rb_iv_set(self, "@group", Qnil);
    if (!NIL_P(group))
        rb_funcall(self, rb_intern("group="), 1, arg);
    return self;
}