static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
{
VALUE arg1, arg2, arg3, arg4;
ossl_ec_group *ec_group;
EC_GROUP *group = NULL;
TypedData_Get_Struct(self, ossl_ec_group, &ossl_ec_group_type, ec_group);
if (ec_group->group != NULL)
ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
case 1:
if (SYMBOL_P(arg1)) {
const EC_METHOD *method = NULL;
ID id = SYM2ID(arg1);
if (id == s_GFp_simple) {
method = EC_GFp_simple_method();
} else if (id == s_GFp_mont) {
method = EC_GFp_mont_method();
} else if (id == s_GFp_nist) {
method = EC_GFp_nist_method();
} else if (id == s_GF2m_simple) {
method = EC_GF2m_simple_method();
}
if (method) {
if ((group = EC_GROUP_new(method)) == NULL)
ossl_raise(eEC_GROUP, "EC_GROUP_new");
} else {
ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
}
} else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
const EC_GROUP *arg1_group;
SafeRequire_EC_GROUP(arg1, arg1_group);
if ((group = EC_GROUP_dup(arg1_group)) == NULL)
ossl_raise(eEC_GROUP, "EC_GROUP_dup");
} else {
BIO *in = ossl_obj2bio(arg1);
group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
if (!group) {
OSSL_BIO_reset(in);
group = d2i_ECPKParameters_bio(in, NULL);
}
BIO_free(in);
if (!group) {
const char *name = StringValueCStr(arg1);
int nid = OBJ_sn2nid(name);
(void)ERR_get_error();
if (nid == NID_undef)
ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
group = EC_GROUP_new_by_curve_name(nid);
if (group == NULL)
ossl_raise(eEC_GROUP, "unable to create curve (%s)", name);
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
}
}
break;
case 4:
if (SYMBOL_P(arg1)) {
ID id = SYM2ID(arg1);
EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
const BIGNUM *p = GetBNPtr(arg2);
const BIGNUM *a = GetBNPtr(arg3);
const BIGNUM *b = GetBNPtr(arg4);
if (id == s_GFp) {
new_curve = EC_GROUP_new_curve_GFp;
} else if (id == s_GF2m) {
new_curve = EC_GROUP_new_curve_GF2m;
} else {
ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
}
if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
} else {
ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
}
break;
default:
ossl_raise(rb_eArgError, "wrong number of arguments");
}
if (group == NULL)
ossl_raise(eEC_GROUP, "");
ec_group->group = group;
return self;
}