7 #if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
24 #define GetPKeyEC(obj, pkey) do { \
25 GetPKey((obj), (pkey)); \
26 if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_EC) { \
27 ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
31 #define SafeGet_ec_group(obj, group) do { \
32 OSSL_Check_Kind((obj), cEC_GROUP); \
33 Data_Get_Struct((obj), ossl_ec_group, (group)); \
36 #define Get_EC_KEY(obj, key) do { \
38 GetPKeyEC((obj), pkey); \
39 (key) = pkey->pkey.ec; \
42 #define Require_EC_KEY(obj, key) do { \
43 Get_EC_KEY((obj), (key)); \
45 ossl_raise(eECError, "EC_KEY is not initialized"); \
48 #define SafeRequire_EC_KEY(obj, key) do { \
49 OSSL_Check_Kind((obj), cEC); \
50 Require_EC_KEY((obj), (key)); \
53 #define Get_EC_GROUP(obj, g) do { \
54 ossl_ec_group *ec_group; \
55 Data_Get_Struct((obj), ossl_ec_group, ec_group); \
56 if (ec_group == NULL) \
57 ossl_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
58 (g) = ec_group->group; \
61 #define Require_EC_GROUP(obj, group) do { \
62 Get_EC_GROUP((obj), (group)); \
63 if ((group) == NULL) \
64 ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
67 #define SafeRequire_EC_GROUP(obj, group) do { \
68 OSSL_Check_Kind((obj), cEC_GROUP); \
69 Require_EC_GROUP((obj), (group)); \
72 #define Get_EC_POINT(obj, p) do { \
73 ossl_ec_point *ec_point; \
74 Data_Get_Struct((obj), ossl_ec_point, ec_point); \
75 if (ec_point == NULL) \
76 ossl_raise(eEC_POINT, "missing ossl_ec_point structure"); \
77 (p) = ec_point->point; \
80 #define Require_EC_POINT(obj, point) do { \
81 Get_EC_POINT((obj), (point)); \
82 if ((point) == NULL) \
83 ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
86 #define SafeRequire_EC_POINT(obj, point) do { \
87 OSSL_Check_Kind((obj), cEC_POINT); \
88 Require_EC_POINT((obj), (point)); \
99 static ID s_GFp_simple;
100 static ID s_GFp_mont;
101 static ID s_GFp_nist;
103 static ID s_GF2m_simple;
105 static ID ID_uncompressed;
106 static ID ID_compressed;
117 if (!(pkey = EVP_PKEY_new())) {
120 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
134 obj = ec_instance(
cEC, EC_KEY_new());
136 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
179 EC_KEY *other_ec =
NULL;
181 SafeRequire_EC_KEY(arg, other_ec);
182 ec = EC_KEY_dup(other_ec);
199 ec = d2i_ECPrivateKey_bio(in,
NULL);
203 ec = d2i_EC_PUBKEY_bio(in,
NULL);
210 int nid = OBJ_sn2nid(name);
212 (
void)ERR_get_error();
213 if (nid == NID_undef)
216 if ((ec = EC_KEY_new_by_curve_name(nid)) ==
NULL)
219 EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
220 EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
228 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
248 static VALUE ossl_ec_key_get_group(
VALUE self)
252 ossl_ec_group *ec_group;
255 Require_EC_KEY(
self, ec);
261 if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) !=
NULL) {
263 SafeGet_ec_group(group_v, ec_group);
264 ec_group->group = group;
265 ec_group->dont_free = 1;
296 Require_EC_KEY(
self, ec);
297 SafeRequire_EC_GROUP(group_v, group);
300 if (!
NIL_P(old_group_v)) {
301 ossl_ec_group *old_ec_group;
302 SafeGet_ec_group(old_group_v, old_ec_group);
304 old_ec_group->group =
NULL;
305 old_ec_group->dont_free = 0;
311 if (EC_KEY_set_group(ec, group) != 1)
323 static VALUE ossl_ec_key_get_private_key(
VALUE self)
328 Require_EC_KEY(
self, ec);
330 if ((bn = EC_KEY_get0_private_key(ec)) ==
NULL)
342 static VALUE ossl_ec_key_set_private_key(
VALUE self,
VALUE private_key)
347 Require_EC_KEY(
self, ec);
348 if (!
NIL_P(private_key))
351 switch (EC_KEY_set_private_key(ec, bn)) {
365 static VALUE ossl_ec_point_dup(
const EC_POINT *point,
VALUE group_v)
368 const EC_GROUP *group;
369 ossl_ec_point *new_point;
374 SafeRequire_EC_GROUP(group_v, group);
376 new_point->point = EC_POINT_dup(point, group);
377 if (new_point->point ==
NULL)
390 static VALUE ossl_ec_key_get_public_key(
VALUE self)
393 const EC_POINT *point;
396 Require_EC_KEY(
self, ec);
398 if ((point = EC_KEY_get0_public_key(ec)) ==
NULL)
405 return ossl_ec_point_dup(point, group);
417 EC_POINT *point =
NULL;
419 Require_EC_KEY(
self, ec);
420 if (!
NIL_P(public_key))
421 SafeRequire_EC_POINT(public_key, point);
423 switch (EC_KEY_set_public_key(ec, point)) {
442 static VALUE ossl_ec_key_is_public_key(
VALUE self)
446 Require_EC_KEY(
self, ec);
448 return (EC_KEY_get0_public_key(ec) ?
Qtrue :
Qfalse);
457 static VALUE ossl_ec_key_is_private_key(
VALUE self)
461 Require_EC_KEY(
self, ec);
463 return (EC_KEY_get0_private_key(ec) ?
Qtrue :
Qfalse);
472 char *password =
NULL;
475 Require_EC_KEY(
self, ec);
477 if (EC_KEY_get0_public_key(ec) ==
NULL)
480 if (EC_KEY_check_key(ec) != 1)
483 if (EC_KEY_get0_private_key(ec))
486 if (!(out = BIO_new(BIO_s_mem())))
492 const EVP_CIPHER *cipher;
505 i = PEM_write_bio_ECPrivateKey(out, ec, cipher,
NULL, 0,
NULL, password);
507 i = PEM_write_bio_EC_PUBKEY(out, ec);
513 i = i2d_ECPrivateKey_bio(out, ec);
515 i = i2d_EC_PUBKEY_bio(out, ec);
548 VALUE cipher, passwd;
550 return ossl_ec_key_to_string(
self, cipher, passwd, EXPORT_PEM);
561 return ossl_ec_key_to_string(
self,
Qnil,
Qnil, EXPORT_DER);
576 Require_EC_KEY(
self, ec);
577 if (!(out = BIO_new(BIO_s_mem()))) {
580 if (!EC_KEY_print(out, ec, 0)) {
595 static VALUE ossl_ec_key_generate_key(
VALUE self)
599 Require_EC_KEY(
self, ec);
601 if (EC_KEY_generate_key(ec) != 1)
615 static VALUE ossl_ec_key_check_key(
VALUE self)
619 Require_EC_KEY(
self, ec);
621 if (EC_KEY_check_key(ec) != 1)
640 Require_EC_KEY(
self, ec);
641 SafeRequire_EC_POINT(pubkey, point);
647 buf_len = ECDH_compute_key(
RSTRING_PTR(str), buf_len, point, ec,
NULL);
667 unsigned int buf_len;
670 Require_EC_KEY(
self, ec);
673 if (EC_KEY_get0_private_key(ec) ==
NULL)
695 Require_EC_KEY(
self, ec);
700 case 1:
return Qtrue;
710 static void ossl_ec_group_free(ossl_ec_group *ec_group)
712 if (!ec_group->dont_free && ec_group->group)
713 EC_GROUP_clear_free(ec_group->group);
719 ossl_ec_group *ec_group;
722 obj =
Data_Make_Struct(klass, ossl_ec_group, 0, ossl_ec_group_free, ec_group);
743 static VALUE ossl_ec_group_initialize(
int argc,
VALUE *argv,
VALUE self)
745 VALUE arg1, arg2, arg3, arg4;
746 ossl_ec_group *ec_group;
747 EC_GROUP *group =
NULL;
750 if (ec_group->group !=
NULL)
753 switch (
rb_scan_args(argc, argv,
"13", &arg1, &arg2, &arg3, &arg4)) {
759 if (
id == s_GFp_simple) {
760 method = EC_GFp_simple_method();
761 }
else if (
id == s_GFp_mont) {
762 method = EC_GFp_mont_method();
763 }
else if (
id == s_GFp_nist) {
764 method = EC_GFp_nist_method();
765 }
else if (
id == s_GF2m_simple) {
766 method = EC_GF2m_simple_method();
770 if ((group = EC_GROUP_new(method)) ==
NULL)
776 const EC_GROUP *arg1_group;
778 SafeRequire_EC_GROUP(arg1, arg1_group);
779 if ((group = EC_GROUP_dup(arg1_group)) ==
NULL)
784 group = PEM_read_bio_ECPKParameters(in,
NULL,
NULL,
NULL);
787 group = d2i_ECPKParameters_bio(in,
NULL);
794 int nid = OBJ_sn2nid(name);
796 (
void)ERR_get_error();
797 if (nid == NID_undef)
800 group = EC_GROUP_new_by_curve_name(nid);
804 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
805 EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
813 EC_GROUP *(*new_curve)(
const BIGNUM *,
const BIGNUM *,
const BIGNUM *, BN_CTX *) =
NULL;
819 new_curve = EC_GROUP_new_curve_GFp;
820 }
else if (
id == s_GF2m) {
821 new_curve = EC_GROUP_new_curve_GF2m;
840 ec_group->group = group;
851 EC_GROUP *group1 =
NULL, *group2 =
NULL;
853 Require_EC_GROUP(a, group1);
854 SafeRequire_EC_GROUP(b, group2);
856 if (EC_GROUP_cmp(group1, group2,
ossl_bn_ctx) == 1)
867 static VALUE ossl_ec_group_get_generator(
VALUE self)
870 EC_GROUP *group =
NULL;
872 Require_EC_GROUP(
self, group);
874 point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group),
self);
886 EC_GROUP *group =
NULL;
887 const EC_POINT *point;
888 const BIGNUM *o, *co;
890 Require_EC_GROUP(
self, group);
891 SafeRequire_EC_POINT(generator, point);
895 if (EC_GROUP_set_generator(group, point, o, co) != 1)
906 static VALUE ossl_ec_group_get_order(
VALUE self)
910 EC_GROUP *group =
NULL;
912 Require_EC_GROUP(
self, group);
917 if (EC_GROUP_get_order(group, bn,
ossl_bn_ctx) != 1)
928 static VALUE ossl_ec_group_get_cofactor(
VALUE self)
932 EC_GROUP *group =
NULL;
934 Require_EC_GROUP(
self, group);
939 if (EC_GROUP_get_cofactor(group, bn,
ossl_bn_ctx) != 1)
950 static VALUE ossl_ec_group_get_curve_name(
VALUE self)
952 EC_GROUP *group =
NULL;
955 Get_EC_GROUP(
self, group);
959 nid = EC_GROUP_get_curve_name(group);
970 static VALUE ossl_s_builtin_curves(
VALUE self)
972 EC_builtin_curve *curves =
NULL;
977 curves =
ALLOCA_N(EC_builtin_curve, crv_len);
980 if (!EC_get_builtin_curves(curves, crv_len))
985 for (n = 0; n < crv_len; n++) {
986 const char *sname = OBJ_nid2sn(curves[n].nid);
987 const char *
comment = curves[
n].comment;
1003 static VALUE ossl_ec_group_get_asn1_flag(
VALUE self)
1005 EC_GROUP *group =
NULL;
1008 Require_EC_GROUP(
self, group);
1010 flag = EC_GROUP_get_asn1_flag(group);
1022 EC_GROUP *group =
NULL;
1024 Require_EC_GROUP(
self, group);
1026 EC_GROUP_set_asn1_flag(group,
NUM2INT(flag_v));
1036 static VALUE ossl_ec_group_get_point_conversion_form(
VALUE self)
1038 EC_GROUP *group =
NULL;
1039 point_conversion_form_t form;
1042 Require_EC_GROUP(
self, group);
1044 form = EC_GROUP_get_point_conversion_form(group);
1047 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed;
break;
1048 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed;
break;
1049 case POINT_CONVERSION_HYBRID: ret = ID_hybrid;
break;
1050 default:
ossl_raise(
eEC_GROUP,
"unsupported point conversion form: %d, this module should be updated", form);
1061 static VALUE ossl_ec_group_set_point_conversion_form(
VALUE self,
VALUE form_v)
1063 EC_GROUP *group =
NULL;
1064 point_conversion_form_t form;
1067 Require_EC_GROUP(
self, group);
1069 if (form_id == ID_uncompressed) {
1070 form = POINT_CONVERSION_UNCOMPRESSED;
1071 }
else if (form_id == ID_compressed) {
1072 form = POINT_CONVERSION_COMPRESSED;
1073 }
else if (form_id == ID_hybrid) {
1074 form = POINT_CONVERSION_HYBRID;
1079 EC_GROUP_set_point_conversion_form(group, form);
1089 static VALUE ossl_ec_group_get_seed(
VALUE self)
1091 EC_GROUP *group =
NULL;
1094 Require_EC_GROUP(
self, group);
1096 seed_len = EC_GROUP_get_seed_len(group);
1101 return rb_str_new((
const char *)EC_GROUP_get0_seed(group), seed_len);
1111 EC_GROUP *group =
NULL;
1113 Require_EC_GROUP(
self, group);
1129 static VALUE ossl_ec_group_get_degree(
VALUE self)
1131 EC_GROUP *group =
NULL;
1133 Require_EC_GROUP(
self, group);
1135 return INT2NUM(EC_GROUP_get_degree(group));
1138 static VALUE ossl_ec_group_to_string(
VALUE self,
int format)
1145 Get_EC_GROUP(
self, group);
1147 if (!(out = BIO_new(BIO_s_mem())))
1152 i = PEM_write_bio_ECPKParameters(out, group);
1155 i = i2d_ECPKParameters_bio(out, group);
1177 static VALUE ossl_ec_group_to_pem(
VALUE self)
1179 return ossl_ec_group_to_string(
self, EXPORT_PEM);
1187 static VALUE ossl_ec_group_to_der(
VALUE self)
1189 return ossl_ec_group_to_string(
self, EXPORT_DER);
1197 static VALUE ossl_ec_group_to_text(
VALUE self)
1203 Require_EC_GROUP(
self, group);
1204 if (!(out = BIO_new(BIO_s_mem()))) {
1207 if (!ECPKParameters_print(out, group, 0)) {
1217 static void ossl_ec_point_free(ossl_ec_point *ec_point)
1219 if (!ec_point->dont_free && ec_point->point)
1220 EC_POINT_clear_free(ec_point->point);
1224 static VALUE ossl_ec_point_alloc(
VALUE klass)
1226 ossl_ec_point *ec_point;
1229 obj =
Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
1242 static VALUE ossl_ec_point_initialize(
int argc,
VALUE *argv,
VALUE self)
1244 ossl_ec_point *ec_point;
1245 EC_POINT *point =
NULL;
1248 const EC_GROUP *group =
NULL;
1251 if (ec_point->point)
1254 switch (
rb_scan_args(argc, argv,
"11", &arg1, &arg2)) {
1257 const EC_POINT *arg_point;
1260 SafeRequire_EC_GROUP(group_v, group);
1261 SafeRequire_EC_POINT(arg1, arg_point);
1263 point = EC_POINT_dup(arg_point, group);
1266 SafeRequire_EC_GROUP(group_v, group);
1268 point = EC_POINT_new(group);
1270 ossl_raise(
eEC_POINT,
"wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1278 SafeRequire_EC_GROUP(group_v, group);
1291 if (point ==
NULL) {
1306 ec_point->point = point;
1320 EC_POINT *point1, *point2;
1323 const EC_GROUP *group;
1325 if (ossl_ec_group_eql(group_v1, group_v2) ==
Qfalse)
1328 Require_EC_POINT(a, point1);
1329 SafeRequire_EC_POINT(b, point2);
1330 SafeRequire_EC_GROUP(group_v1, group);
1332 if (EC_POINT_cmp(group, point1, point2,
ossl_bn_ctx) == 1)
1343 static VALUE ossl_ec_point_is_at_infinity(
VALUE self)
1347 const EC_GROUP *group;
1349 Require_EC_POINT(
self, point);
1350 SafeRequire_EC_GROUP(group_v, group);
1352 switch (EC_POINT_is_at_infinity(group, point)) {
1353 case 1:
return Qtrue;
1366 static VALUE ossl_ec_point_is_on_curve(
VALUE self)
1370 const EC_GROUP *group;
1372 Require_EC_POINT(
self, point);
1373 SafeRequire_EC_GROUP(group_v, group);
1375 switch (EC_POINT_is_on_curve(group, point,
ossl_bn_ctx)) {
1376 case 1:
return Qtrue;
1389 static VALUE ossl_ec_point_make_affine(
VALUE self)
1393 const EC_GROUP *group;
1395 Require_EC_POINT(
self, point);
1396 SafeRequire_EC_GROUP(group_v, group);
1398 if (EC_POINT_make_affine(group, point,
ossl_bn_ctx) != 1)
1409 static VALUE ossl_ec_point_invert(
VALUE self)
1413 const EC_GROUP *group;
1415 Require_EC_POINT(
self, point);
1416 SafeRequire_EC_GROUP(group_v, group);
1418 if (EC_POINT_invert(group, point,
ossl_bn_ctx) != 1)
1429 static VALUE ossl_ec_point_set_to_infinity(
VALUE self)
1433 const EC_GROUP *group;
1435 Require_EC_POINT(
self, point);
1436 SafeRequire_EC_GROUP(group_v, group);
1438 if (EC_POINT_set_to_infinity(group, point) != 1)
1455 const EC_GROUP *group;
1456 point_conversion_form_t form;
1459 Require_EC_POINT(
self, point);
1460 SafeRequire_EC_GROUP(group_v, group);
1462 form = EC_GROUP_get_point_conversion_form(group);
1482 EC_POINT *point1, *point2;
1483 const EC_GROUP *group;
1485 VALUE bn_v1, bn_v2,
r, points_v;
1488 Require_EC_POINT(
self, point1);
1489 SafeRequire_EC_GROUP(group_v, group);
1492 ossl_ec_point_initialize(1, &group_v, r);
1493 Require_EC_POINT(r, point2);
1495 argc =
rb_scan_args(argc, argv,
"12", &bn_v1, &points_v, &bn_v2);
1502 if (EC_POINT_mul(group, point2, bn2, point1, bn1,
ossl_bn_ctx) != 1)
1505 size_t i, points_len, bignums_len;
1506 const EC_POINT **points;
1507 const BIGNUM **bignums;
1511 bignums = (
const BIGNUM **)OPENSSL_malloc(bignums_len * (
int)
sizeof(BIGNUM *));
1513 for (i = 0; i < bignums_len; ++
i) {
1518 OPENSSL_free((
void *)bignums);
1524 points = (
const EC_POINT **)OPENSSL_malloc(points_len * (
int)
sizeof(EC_POINT *));
1526 for (i = 0; i < points_len; ++
i) {
1533 if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums,
ossl_bn_ctx) != 1) {
1534 OPENSSL_free((
void *)bignums);
1535 OPENSSL_free((
void *)points);
1538 OPENSSL_free((
void *)bignums);
1539 OPENSSL_free((
void *)points);
1545 static void no_copy(
VALUE klass)
1555 #ifdef DONT_NEED_RDOC_WORKAROUND
1573 s_GF2m_simple =
rb_intern(
"GF2m_simple");
1575 ID_uncompressed =
rb_intern(
"uncompressed");
1576 ID_compressed =
rb_intern(
"compressed");
1579 #ifdef OPENSSL_EC_NAMED_CURVE
VALUE rb_ary_unshift(VALUE ary, VALUE item)
VALUE rb_ary_entry(VALUE ary, long offset)
VALUE rb_iv_set(VALUE, const char *, VALUE)
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
#define Data_Make_Struct(klass, type, mark, free, sval)
VALUE rb_iv_get(VALUE, const char *)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_raise(VALUE exc, const char *fmt,...)
#define GetPKey(obj, pkey)
VALUE ossl_membio2str(BIO *bio)
void rb_undef_method(VALUE klass, const char *name)
#define StringValuePtr(v)
#define StringValueCStr(v)
#define OSSL_BIO_reset(bio)
void rb_define_const(VALUE, const char *, VALUE)
const EVP_CIPHER * GetCipherPtr(VALUE obj)
#define ALLOCA_N(type, n)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
VALUE rb_str_resize(VALUE, long)
#define WrapPKey(klass, obj, pkey)
BIO * ossl_obj2bio(VALUE obj)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
void rb_attr(VALUE, ID, int, int, int)
VALUE rb_define_module_under(VALUE outer, const char *name)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
RUBY_EXTERN VALUE rb_cObject
#define Data_Get_Struct(obj, type, sval)
void ossl_raise(VALUE exc, const char *fmt,...)
#define RSTRING_LENINT(str)
VALUE rb_ary_new2(long capa)
VALUE rb_str_new(const char *, long)
VALUE rb_obj_alloc(VALUE)
VALUE ossl_bn_new(const BIGNUM *bn)
int ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
BIGNUM * GetBNPtr(VALUE obj)
VALUE rb_define_module(const char *name)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE ossl_ec_new(EVP_PKEY *)