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 #if !defined(OPENSSL_NO_EC2M)
766 }
else if (
id == s_GF2m_simple) {
767 method = EC_GF2m_simple_method();
772 if ((group = EC_GROUP_new(method)) ==
NULL)
778 const EC_GROUP *arg1_group;
780 SafeRequire_EC_GROUP(arg1, arg1_group);
781 if ((group = EC_GROUP_dup(arg1_group)) ==
NULL)
786 group = PEM_read_bio_ECPKParameters(in,
NULL,
NULL,
NULL);
789 group = d2i_ECPKParameters_bio(in,
NULL);
796 int nid = OBJ_sn2nid(name);
798 (
void)ERR_get_error();
799 if (nid == NID_undef)
802 group = EC_GROUP_new_by_curve_name(nid);
806 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
807 EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
815 EC_GROUP *(*new_curve)(
const BIGNUM *,
const BIGNUM *,
const BIGNUM *, BN_CTX *) =
NULL;
821 new_curve = EC_GROUP_new_curve_GFp;
822 #if !defined(OPENSSL_NO_EC2M)
823 }
else if (
id == s_GF2m) {
824 new_curve = EC_GROUP_new_curve_GF2m;
844 ec_group->group = group;
855 EC_GROUP *group1 =
NULL, *group2 =
NULL;
857 Require_EC_GROUP(a, group1);
858 SafeRequire_EC_GROUP(b, group2);
860 if (EC_GROUP_cmp(group1, group2,
ossl_bn_ctx) == 1)
871 static VALUE ossl_ec_group_get_generator(
VALUE self)
874 EC_GROUP *group =
NULL;
876 Require_EC_GROUP(
self, group);
878 point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group),
self);
890 EC_GROUP *group =
NULL;
891 const EC_POINT *point;
892 const BIGNUM *o, *co;
894 Require_EC_GROUP(
self, group);
895 SafeRequire_EC_POINT(generator, point);
899 if (EC_GROUP_set_generator(group, point, o, co) != 1)
910 static VALUE ossl_ec_group_get_order(
VALUE self)
914 EC_GROUP *group =
NULL;
916 Require_EC_GROUP(
self, group);
921 if (EC_GROUP_get_order(group, bn,
ossl_bn_ctx) != 1)
932 static VALUE ossl_ec_group_get_cofactor(
VALUE self)
936 EC_GROUP *group =
NULL;
938 Require_EC_GROUP(
self, group);
943 if (EC_GROUP_get_cofactor(group, bn,
ossl_bn_ctx) != 1)
954 static VALUE ossl_ec_group_get_curve_name(
VALUE self)
956 EC_GROUP *group =
NULL;
959 Get_EC_GROUP(
self, group);
963 nid = EC_GROUP_get_curve_name(group);
974 static VALUE ossl_s_builtin_curves(
VALUE self)
976 EC_builtin_curve *curves =
NULL;
981 curves =
ALLOCA_N(EC_builtin_curve, crv_len);
984 if (!EC_get_builtin_curves(curves, crv_len))
989 for (n = 0; n < crv_len; n++) {
990 const char *sname = OBJ_nid2sn(curves[n].nid);
991 const char *
comment = curves[
n].comment;
1007 static VALUE ossl_ec_group_get_asn1_flag(
VALUE self)
1009 EC_GROUP *group =
NULL;
1012 Require_EC_GROUP(
self, group);
1014 flag = EC_GROUP_get_asn1_flag(group);
1026 EC_GROUP *group =
NULL;
1028 Require_EC_GROUP(
self, group);
1030 EC_GROUP_set_asn1_flag(group,
NUM2INT(flag_v));
1040 static VALUE ossl_ec_group_get_point_conversion_form(
VALUE self)
1042 EC_GROUP *group =
NULL;
1043 point_conversion_form_t form;
1046 Require_EC_GROUP(
self, group);
1048 form = EC_GROUP_get_point_conversion_form(group);
1051 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed;
break;
1052 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed;
break;
1053 case POINT_CONVERSION_HYBRID: ret = ID_hybrid;
break;
1054 default:
ossl_raise(
eEC_GROUP,
"unsupported point conversion form: %d, this module should be updated", form);
1065 static VALUE ossl_ec_group_set_point_conversion_form(
VALUE self,
VALUE form_v)
1067 EC_GROUP *group =
NULL;
1068 point_conversion_form_t form;
1071 Require_EC_GROUP(
self, group);
1073 if (form_id == ID_uncompressed) {
1074 form = POINT_CONVERSION_UNCOMPRESSED;
1075 }
else if (form_id == ID_compressed) {
1076 form = POINT_CONVERSION_COMPRESSED;
1077 }
else if (form_id == ID_hybrid) {
1078 form = POINT_CONVERSION_HYBRID;
1083 EC_GROUP_set_point_conversion_form(group, form);
1093 static VALUE ossl_ec_group_get_seed(
VALUE self)
1095 EC_GROUP *group =
NULL;
1098 Require_EC_GROUP(
self, group);
1100 seed_len = EC_GROUP_get_seed_len(group);
1105 return rb_str_new((
const char *)EC_GROUP_get0_seed(group), seed_len);
1115 EC_GROUP *group =
NULL;
1117 Require_EC_GROUP(
self, group);
1133 static VALUE ossl_ec_group_get_degree(
VALUE self)
1135 EC_GROUP *group =
NULL;
1137 Require_EC_GROUP(
self, group);
1139 return INT2NUM(EC_GROUP_get_degree(group));
1142 static VALUE ossl_ec_group_to_string(
VALUE self,
int format)
1149 Get_EC_GROUP(
self, group);
1151 if (!(out = BIO_new(BIO_s_mem())))
1156 i = PEM_write_bio_ECPKParameters(out, group);
1159 i = i2d_ECPKParameters_bio(out, group);
1181 static VALUE ossl_ec_group_to_pem(
VALUE self)
1183 return ossl_ec_group_to_string(
self, EXPORT_PEM);
1191 static VALUE ossl_ec_group_to_der(
VALUE self)
1193 return ossl_ec_group_to_string(
self, EXPORT_DER);
1201 static VALUE ossl_ec_group_to_text(
VALUE self)
1207 Require_EC_GROUP(
self, group);
1208 if (!(out = BIO_new(BIO_s_mem()))) {
1211 if (!ECPKParameters_print(out, group, 0)) {
1221 static void ossl_ec_point_free(ossl_ec_point *ec_point)
1223 if (!ec_point->dont_free && ec_point->point)
1224 EC_POINT_clear_free(ec_point->point);
1228 static VALUE ossl_ec_point_alloc(
VALUE klass)
1230 ossl_ec_point *ec_point;
1233 obj =
Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
1246 static VALUE ossl_ec_point_initialize(
int argc,
VALUE *argv,
VALUE self)
1248 ossl_ec_point *ec_point;
1249 EC_POINT *point =
NULL;
1252 const EC_GROUP *group =
NULL;
1255 if (ec_point->point)
1258 switch (
rb_scan_args(argc, argv,
"11", &arg1, &arg2)) {
1261 const EC_POINT *arg_point;
1264 SafeRequire_EC_GROUP(group_v, group);
1265 SafeRequire_EC_POINT(arg1, arg_point);
1267 point = EC_POINT_dup(arg_point, group);
1270 SafeRequire_EC_GROUP(group_v, group);
1272 point = EC_POINT_new(group);
1274 ossl_raise(
eEC_POINT,
"wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1282 SafeRequire_EC_GROUP(group_v, group);
1295 if (point ==
NULL) {
1310 ec_point->point = point;
1324 EC_POINT *point1, *point2;
1327 const EC_GROUP *group;
1329 if (ossl_ec_group_eql(group_v1, group_v2) ==
Qfalse)
1332 Require_EC_POINT(a, point1);
1333 SafeRequire_EC_POINT(b, point2);
1334 SafeRequire_EC_GROUP(group_v1, group);
1336 if (EC_POINT_cmp(group, point1, point2,
ossl_bn_ctx) == 1)
1347 static VALUE ossl_ec_point_is_at_infinity(
VALUE self)
1351 const EC_GROUP *group;
1353 Require_EC_POINT(
self, point);
1354 SafeRequire_EC_GROUP(group_v, group);
1356 switch (EC_POINT_is_at_infinity(group, point)) {
1357 case 1:
return Qtrue;
1370 static VALUE ossl_ec_point_is_on_curve(
VALUE self)
1374 const EC_GROUP *group;
1376 Require_EC_POINT(
self, point);
1377 SafeRequire_EC_GROUP(group_v, group);
1379 switch (EC_POINT_is_on_curve(group, point,
ossl_bn_ctx)) {
1380 case 1:
return Qtrue;
1393 static VALUE ossl_ec_point_make_affine(
VALUE self)
1397 const EC_GROUP *group;
1399 Require_EC_POINT(
self, point);
1400 SafeRequire_EC_GROUP(group_v, group);
1402 if (EC_POINT_make_affine(group, point,
ossl_bn_ctx) != 1)
1413 static VALUE ossl_ec_point_invert(
VALUE self)
1417 const EC_GROUP *group;
1419 Require_EC_POINT(
self, point);
1420 SafeRequire_EC_GROUP(group_v, group);
1422 if (EC_POINT_invert(group, point,
ossl_bn_ctx) != 1)
1433 static VALUE ossl_ec_point_set_to_infinity(
VALUE self)
1437 const EC_GROUP *group;
1439 Require_EC_POINT(
self, point);
1440 SafeRequire_EC_GROUP(group_v, group);
1442 if (EC_POINT_set_to_infinity(group, point) != 1)
1459 const EC_GROUP *group;
1460 point_conversion_form_t form;
1463 Require_EC_POINT(
self, point);
1464 SafeRequire_EC_GROUP(group_v, group);
1466 form = EC_GROUP_get_point_conversion_form(group);
1486 EC_POINT *point1, *point2;
1487 const EC_GROUP *group;
1489 VALUE bn_v1, bn_v2,
r, points_v;
1492 Require_EC_POINT(
self, point1);
1493 SafeRequire_EC_GROUP(group_v, group);
1496 ossl_ec_point_initialize(1, &group_v, r);
1497 Require_EC_POINT(r, point2);
1499 argc =
rb_scan_args(argc, argv,
"12", &bn_v1, &points_v, &bn_v2);
1506 if (EC_POINT_mul(group, point2, bn2, point1, bn1,
ossl_bn_ctx) != 1)
1509 size_t i, points_len, bignums_len;
1510 const EC_POINT **points;
1511 const BIGNUM **bignums;
1515 bignums = (
const BIGNUM **)OPENSSL_malloc(bignums_len * (
int)
sizeof(BIGNUM *));
1517 for (i = 0; i < bignums_len; ++
i) {
1522 OPENSSL_free((
void *)bignums);
1528 points = (
const EC_POINT **)OPENSSL_malloc(points_len * (
int)
sizeof(EC_POINT *));
1530 for (i = 0; i < points_len; ++
i) {
1537 if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums,
ossl_bn_ctx) != 1) {
1538 OPENSSL_free((
void *)bignums);
1539 OPENSSL_free((
void *)points);
1542 OPENSSL_free((
void *)bignums);
1543 OPENSSL_free((
void *)points);
1549 static void no_copy(
VALUE klass)
1559 #ifdef DONT_NEED_RDOC_WORKAROUND
1577 s_GF2m_simple =
rb_intern(
"GF2m_simple");
1579 ID_uncompressed =
rb_intern(
"uncompressed");
1580 ID_compressed =
rb_intern(
"compressed");
1583 #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 *)