7 #if !defined(OPENSSL_NO_EC) 15 #define GetPKeyEC(obj, pkey) do { \ 16 GetPKey((obj), (pkey)); \ 17 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { \ 18 ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \ 21 #define GetEC(obj, key) do { \ 23 GetPKeyEC(obj, _pkey); \ 24 (key) = EVP_PKEY_get0_EC_KEY(_pkey); \ 27 #define GetECGroup(obj, group) do { \ 28 TypedData_Get_Struct(obj, EC_GROUP, &ossl_ec_group_type, group); \ 29 if ((group) == NULL) \ 30 ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \ 33 #define GetECPoint(obj, point) do { \ 34 TypedData_Get_Struct(obj, EC_POINT, &ossl_ec_point_type, point); \ 35 if ((point) == NULL) \ 36 ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \ 38 #define GetECPointGroup(obj, group) do { \ 39 VALUE _group = rb_attr_get(obj, id_i_group); \ 40 GetECGroup(_group, group); \ 51 static ID s_GFp_simple;
55 static ID s_GF2m_simple;
57 static ID ID_uncompressed;
58 static ID ID_compressed;
63 static VALUE ec_group_new(
const EC_GROUP *group);
64 static VALUE ec_point_new(
const EC_POINT *point,
const EC_GROUP *group);
66 static VALUE ec_instance(
VALUE klass, EC_KEY *ec)
75 if (!(pkey = EVP_PKEY_new())) {
78 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
92 obj = ec_instance(
cEC, EC_KEY_new());
95 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) {
112 ec_key_new_from_group(
VALUE arg)
120 if (!(ec = EC_KEY_new()))
123 if (!EC_KEY_set_group(ec, group)) {
130 if (nid == NID_undef)
133 if (!(ec = EC_KEY_new_by_curve_name(nid)))
136 EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
137 EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
151 ossl_ec_key_s_generate(
VALUE klass,
VALUE arg)
156 ec = ec_key_new_from_group(arg);
158 obj = ec_instance(klass, ec);
164 if (!EC_KEY_generate_key(ec))
188 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
194 if (!(ec = EC_KEY_new()))
197 EC_KEY *other_ec =
NULL;
199 GetEC(arg, other_ec);
200 if (!(ec = EC_KEY_dup(other_ec)))
203 ec = ec_key_new_from_group(arg);
217 ec = d2i_ECPrivateKey_bio(in,
NULL);
221 ec = d2i_EC_PUBKEY_bio(in,
NULL);
227 ec = ec_key_new_from_group(arg);
231 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
240 ossl_ec_key_initialize_copy(
VALUE self,
VALUE other)
246 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
250 ec_new = EC_KEY_dup(ec);
253 if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) {
269 ossl_ec_key_get_group(
VALUE self)
272 const EC_GROUP *group;
275 group = EC_KEY_get0_group(ec);
279 return ec_group_new(group);
290 ossl_ec_key_set_group(
VALUE self,
VALUE group_v)
298 if (EC_KEY_set_group(ec, group) != 1)
310 static VALUE ossl_ec_key_get_private_key(
VALUE self)
316 if ((bn = EC_KEY_get0_private_key(ec)) ==
NULL)
328 static VALUE ossl_ec_key_set_private_key(
VALUE self,
VALUE private_key)
334 if (!
NIL_P(private_key))
337 switch (EC_KEY_set_private_key(ec, bn)) {
356 static VALUE ossl_ec_key_get_public_key(
VALUE self)
359 const EC_POINT *point;
362 if ((point = EC_KEY_get0_public_key(ec)) ==
NULL)
365 return ec_point_new(point, EC_KEY_get0_group(ec));
377 EC_POINT *point =
NULL;
380 if (!
NIL_P(public_key))
383 switch (EC_KEY_set_public_key(ec, point)) {
403 static VALUE ossl_ec_key_is_public(
VALUE self)
409 return EC_KEY_get0_public_key(ec) ?
Qtrue :
Qfalse;
419 static VALUE ossl_ec_key_is_private(
VALUE self)
425 return EC_KEY_get0_private_key(ec) ?
Qtrue :
Qfalse;
435 const EVP_CIPHER *cipher =
NULL;
439 if (EC_KEY_get0_public_key(ec) ==
NULL)
442 if (EC_KEY_check_key(ec) != 1)
445 if (EC_KEY_get0_private_key(ec))
453 if (!(out = BIO_new(BIO_s_mem())))
461 i = PEM_write_bio_EC_PUBKEY(out, ec);
467 i = i2d_ECPrivateKey_bio(out, ec);
469 i = i2d_EC_PUBKEY_bio(out, ec);
500 VALUE cipher, passwd;
502 return ossl_ec_key_to_string(
self, cipher, passwd,
EXPORT_PEM);
529 if (!(out = BIO_new(BIO_s_mem()))) {
532 if (!EC_KEY_print(out, ec, 0)) {
555 static VALUE ossl_ec_key_generate_key(
VALUE self)
560 if (EC_KEY_generate_key(ec) != 1)
574 static VALUE ossl_ec_key_check_key(
VALUE self)
579 if (EC_KEY_check_key(ec) != 1)
605 buf_len = ECDH_compute_key(
RSTRING_PTR(str), buf_len, point, ec,
NULL);
625 unsigned int buf_len;
631 if (EC_KEY_get0_private_key(ec) ==
NULL)
657 case 1:
return Qtrue;
671 ossl_ec_group_free(
void *ptr)
673 EC_GROUP_clear_free(ptr);
679 0, ossl_ec_group_free,
685 ossl_ec_group_alloc(
VALUE klass)
691 ec_group_new(
const EC_GROUP *group)
697 group_new = EC_GROUP_dup(group);
726 static VALUE ossl_ec_group_initialize(
int argc,
VALUE *argv,
VALUE self)
728 VALUE arg1, arg2, arg3, arg4;
735 switch (
rb_scan_args(argc, argv,
"13", &arg1, &arg2, &arg3, &arg4)) {
738 const EC_METHOD *method =
NULL;
741 if (
id == s_GFp_simple) {
742 method = EC_GFp_simple_method();
743 }
else if (
id == s_GFp_mont) {
744 method = EC_GFp_mont_method();
745 }
else if (
id == s_GFp_nist) {
746 method = EC_GFp_nist_method();
747 #if !defined(OPENSSL_NO_EC2M) 748 }
else if (
id == s_GF2m_simple) {
749 method = EC_GF2m_simple_method();
754 if ((group = EC_GROUP_new(method)) ==
NULL)
760 const EC_GROUP *arg1_group;
763 if ((group = EC_GROUP_dup(arg1_group)) ==
NULL)
768 group = PEM_read_bio_ECPKParameters(in,
NULL,
NULL,
NULL);
771 group = d2i_ECPKParameters_bio(in,
NULL);
778 int nid = OBJ_sn2nid(name);
781 if (nid == NID_undef)
784 group = EC_GROUP_new_by_curve_name(nid);
788 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
789 EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
797 EC_GROUP *(*new_curve)(
const BIGNUM *,
const BIGNUM *,
const BIGNUM *, BN_CTX *) =
NULL;
803 new_curve = EC_GROUP_new_curve_GFp;
804 #if !defined(OPENSSL_NO_EC2M) 805 }
else if (
id == s_GF2m) {
806 new_curve = EC_GROUP_new_curve_GF2m;
831 ossl_ec_group_initialize_copy(
VALUE self,
VALUE other)
833 EC_GROUP *group, *group_new;
840 group_new = EC_GROUP_dup(group);
858 EC_GROUP *group1 =
NULL, *group2 =
NULL;
863 if (EC_GROUP_cmp(group1, group2,
ossl_bn_ctx) == 1)
877 static VALUE ossl_ec_group_get_generator(
VALUE self)
883 generator = EC_GROUP_get0_generator(group);
887 return ec_point_new(generator, group);
901 EC_GROUP *group =
NULL;
902 const EC_POINT *point;
903 const BIGNUM *o, *co;
910 if (EC_GROUP_set_generator(group, point, o, co) != 1)
924 static VALUE ossl_ec_group_get_order(
VALUE self)
928 EC_GROUP *group =
NULL;
935 if (EC_GROUP_get_order(group, bn,
ossl_bn_ctx) != 1)
949 static VALUE ossl_ec_group_get_cofactor(
VALUE self)
953 EC_GROUP *group =
NULL;
960 if (EC_GROUP_get_cofactor(group, bn,
ossl_bn_ctx) != 1)
974 static VALUE ossl_ec_group_get_curve_name(
VALUE self)
976 EC_GROUP *group =
NULL;
983 nid = EC_GROUP_get_curve_name(group);
998 static VALUE ossl_s_builtin_curves(
VALUE self)
1000 EC_builtin_curve *curves =
NULL;
1005 curves =
ALLOCA_N(EC_builtin_curve, crv_len);
1008 if (!EC_get_builtin_curves(curves, crv_len))
1013 for (n = 0; n < crv_len; n++) {
1014 const char *sname = OBJ_nid2sn(curves[n].
nid);
1015 const char *comment = curves[n].comment;
1034 static VALUE ossl_ec_group_get_asn1_flag(
VALUE self)
1036 EC_GROUP *group =
NULL;
1040 flag = EC_GROUP_get_asn1_flag(group);
1061 EC_GROUP *group =
NULL;
1064 EC_GROUP_set_asn1_flag(group,
NUM2INT(flag_v));
1077 static VALUE ossl_ec_group_get_point_conversion_form(
VALUE self)
1079 EC_GROUP *group =
NULL;
1080 point_conversion_form_t form;
1084 form = EC_GROUP_get_point_conversion_form(group);
1087 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed;
break;
1088 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed;
break;
1089 case POINT_CONVERSION_HYBRID: ret = ID_hybrid;
break;
1090 default:
ossl_raise(
eEC_GROUP,
"unsupported point conversion form: %d, this module should be updated", form);
1096 static point_conversion_form_t
1097 parse_point_conversion_form_symbol(
VALUE sym)
1101 if (
id == ID_uncompressed)
1102 return POINT_CONVERSION_UNCOMPRESSED;
1103 else if (
id == ID_compressed)
1104 return POINT_CONVERSION_COMPRESSED;
1105 else if (
id == ID_hybrid)
1106 return POINT_CONVERSION_HYBRID;
1109 " (expected :compressed, :uncompressed, or :hybrid)", sym);
1132 ossl_ec_group_set_point_conversion_form(
VALUE self,
VALUE form_v)
1135 point_conversion_form_t form;
1138 form = parse_point_conversion_form_symbol(form_v);
1140 EC_GROUP_set_point_conversion_form(group, form);
1151 static VALUE ossl_ec_group_get_seed(
VALUE self)
1153 EC_GROUP *group =
NULL;
1157 seed_len = EC_GROUP_get_seed_len(group);
1162 return rb_str_new((
const char *)EC_GROUP_get0_seed(group), seed_len);
1173 EC_GROUP *group =
NULL;
1192 static VALUE ossl_ec_group_get_degree(
VALUE self)
1194 EC_GROUP *group =
NULL;
1198 return INT2NUM(EC_GROUP_get_degree(group));
1201 static VALUE ossl_ec_group_to_string(
VALUE self,
int format)
1210 if (!(out = BIO_new(BIO_s_mem())))
1215 i = PEM_write_bio_ECPKParameters(out, group);
1218 i = i2d_ECPKParameters_bio(out, group);
1241 static VALUE ossl_ec_group_to_pem(
VALUE self)
1243 return ossl_ec_group_to_string(
self,
EXPORT_PEM);
1252 static VALUE ossl_ec_group_to_der(
VALUE self)
1254 return ossl_ec_group_to_string(
self,
EXPORT_DER);
1263 static VALUE ossl_ec_group_to_text(
VALUE self)
1270 if (!(out = BIO_new(BIO_s_mem()))) {
1273 if (!ECPKParameters_print(out, group, 0)) {
1287 ossl_ec_point_free(
void *ptr)
1289 EC_POINT_clear_free(ptr);
1295 0, ossl_ec_point_free,
1301 ossl_ec_point_alloc(
VALUE klass)
1307 ec_point_new(
const EC_POINT *point,
const EC_GROUP *group)
1309 EC_POINT *point_new;
1313 point_new = EC_POINT_dup(point, group);
1317 rb_ivar_set(obj, id_i_group, ec_group_new(group));
1330 static VALUE ossl_ec_point_initialize(
int argc,
VALUE *argv,
VALUE self)
1335 const EC_GROUP *group =
NULL;
1341 switch (
rb_scan_args(argc, argv,
"11", &arg1, &arg2)) {
1344 const EC_POINT *arg_point;
1350 point = EC_POINT_dup(arg_point, group);
1355 point = EC_POINT_new(group);
1357 ossl_raise(
eEC_POINT,
"wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1378 if (point ==
NULL) {
1400 ossl_ec_point_initialize_copy(
VALUE self,
VALUE other)
1402 EC_POINT *point, *point_new;
1414 point_new = EC_POINT_dup(point, group);
1430 EC_POINT *point1, *point2;
1433 const EC_GROUP *group;
1435 if (ossl_ec_group_eql(group_v1, group_v2) ==
Qfalse)
1442 if (EC_POINT_cmp(group, point1, point2,
ossl_bn_ctx) == 1)
1452 static VALUE ossl_ec_point_is_at_infinity(
VALUE self)
1455 const EC_GROUP *group;
1460 switch (EC_POINT_is_at_infinity(group, point)) {
1461 case 1:
return Qtrue;
1473 static VALUE ossl_ec_point_is_on_curve(
VALUE self)
1476 const EC_GROUP *group;
1481 switch (EC_POINT_is_on_curve(group, point,
ossl_bn_ctx)) {
1482 case 1:
return Qtrue;
1494 static VALUE ossl_ec_point_make_affine(
VALUE self)
1497 const EC_GROUP *group;
1502 if (EC_POINT_make_affine(group, point,
ossl_bn_ctx) != 1)
1512 static VALUE ossl_ec_point_invert(
VALUE self)
1515 const EC_GROUP *group;
1520 if (EC_POINT_invert(group, point,
ossl_bn_ctx) != 1)
1530 static VALUE ossl_ec_point_set_to_infinity(
VALUE self)
1533 const EC_GROUP *group;
1538 if (EC_POINT_set_to_infinity(group, point) != 1)
1555 ossl_ec_point_to_bn(
int argc,
VALUE *argv,
VALUE self)
1558 VALUE form_obj, bn_obj;
1559 const EC_GROUP *group;
1560 point_conversion_form_t form;
1566 if (
NIL_P(form_obj))
1567 form = EC_GROUP_get_point_conversion_form(group);
1569 form = parse_point_conversion_form_symbol(form_obj);
1599 EC_POINT *point_self, *point_result;
1600 const EC_GROUP *group;
1603 const BIGNUM *bn_g =
NULL;
1609 ossl_ec_point_initialize(1, &group_v, result);
1618 if (EC_POINT_mul(group, point_result, bn_g, point_self, bn,
ossl_bn_ctx) != 1)
1626 VALUE bns_tmp, tmp_p, tmp_b;
1627 const EC_POINT **points;
1628 const BIGNUM **bignums;
1637 bignums =
ALLOCV_N(
const BIGNUM *, tmp_b, num);
1638 for (i = 0; i < num; i++) {
1644 points =
ALLOCV_N(
const EC_POINT *, tmp_p, num);
1645 points[0] = point_self;
1646 for (i = 0; i < num - 1; i++)
1652 if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums,
ossl_bn_ctx) != 1) {
1702 s_GF2m_simple =
rb_intern(
"GF2m_simple");
1704 ID_uncompressed =
rb_intern(
"uncompressed");
1705 ID_compressed =
rb_intern(
"compressed");
1709 #if defined(OPENSSL_EC_EXPLICIT_CURVE)
#define RUBY_TYPED_FREE_IMMEDIATELY
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
#define SetPKey(obj, pkey)
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define TypedData_Get_Struct(obj, type, data_type, sval)
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_ary_tmp_new(long capa)
BIO * ossl_obj2bio(volatile VALUE *pobj)
void rb_str_set_len(VALUE, long)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_obj_dup(VALUE)
call-seq: obj.dup -> an_object
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_alloc(VALUE)
Allocates an instance of klass.
#define GetPKey(obj, pkey)
VALUE ossl_membio2str(BIO *bio)
#define GetECPointGroup(obj, group)
#define RB_TYPE_P(obj, type)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
void ossl_clear_error(void)
RUBY_EXTERN VALUE rb_cObject
void rb_attr(VALUE, ID, int, int, int)
const EVP_CIPHER * ossl_evp_get_cipherbyname(VALUE obj)
#define OSSL_BIO_reset(bio)
void rb_define_const(VALUE, const char *, VALUE)
#define ALLOCV_N(type, v, n)
#define ALLOCA_N(type, n)
VALUE rb_str_resize(VALUE, long)
int ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_ivar_set(VALUE, ID, VALUE)
VALUE ossl_pem_passwd_value(VALUE pass)
#define GetECPoint(obj, point)
VALUE rb_define_module_under(VALUE outer, const char *name)
#define StringValueCStr(v)
#define RARRAY_AREF(a, i)
void ossl_raise(VALUE exc, const char *fmt,...)
VALUE ossl_bn_new(const BIGNUM *bn)
#define RTYPEDDATA_DATA(v)
#define RSTRING_LENINT(str)
VALUE ossl_ec_new(EVP_PKEY *pkey)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_attr_get(VALUE, ID)
#define GetECGroup(obj, group)
VALUE rb_str_new(const char *, long)