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;
856 EC_GROUP *group1 =
NULL, *group2 =
NULL;
858 Require_EC_GROUP(a, group1);
859 SafeRequire_EC_GROUP(b, group2);
861 if (EC_GROUP_cmp(group1, group2,
ossl_bn_ctx) == 1)
872 static VALUE ossl_ec_group_get_generator(
VALUE self)
875 EC_GROUP *group =
NULL;
877 Require_EC_GROUP(
self, group);
879 point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group),
self);
891 EC_GROUP *group =
NULL;
892 const EC_POINT *point;
893 const BIGNUM *o, *co;
895 Require_EC_GROUP(
self, group);
896 SafeRequire_EC_POINT(generator, point);
900 if (EC_GROUP_set_generator(group, point, o, co) != 1)
911 static VALUE ossl_ec_group_get_order(
VALUE self)
915 EC_GROUP *group =
NULL;
917 Require_EC_GROUP(
self, group);
922 if (EC_GROUP_get_order(group, bn,
ossl_bn_ctx) != 1)
933 static VALUE ossl_ec_group_get_cofactor(
VALUE self)
937 EC_GROUP *group =
NULL;
939 Require_EC_GROUP(
self, group);
944 if (EC_GROUP_get_cofactor(group, bn,
ossl_bn_ctx) != 1)
955 static VALUE ossl_ec_group_get_curve_name(
VALUE self)
957 EC_GROUP *group =
NULL;
960 Get_EC_GROUP(
self, group);
964 nid = EC_GROUP_get_curve_name(group);
975 static VALUE ossl_s_builtin_curves(
VALUE self)
977 EC_builtin_curve *curves =
NULL;
982 curves =
ALLOCA_N(EC_builtin_curve, crv_len);
985 if (!EC_get_builtin_curves(curves, crv_len))
990 for (n = 0; n < crv_len; n++) {
991 const char *sname = OBJ_nid2sn(curves[n].nid);
992 const char *
comment = curves[
n].comment;
1008 static VALUE ossl_ec_group_get_asn1_flag(
VALUE self)
1010 EC_GROUP *group =
NULL;
1013 Require_EC_GROUP(
self, group);
1015 flag = EC_GROUP_get_asn1_flag(group);
1027 EC_GROUP *group =
NULL;
1029 Require_EC_GROUP(
self, group);
1031 EC_GROUP_set_asn1_flag(group,
NUM2INT(flag_v));
1041 static VALUE ossl_ec_group_get_point_conversion_form(
VALUE self)
1043 EC_GROUP *group =
NULL;
1044 point_conversion_form_t form;
1047 Require_EC_GROUP(
self, group);
1049 form = EC_GROUP_get_point_conversion_form(group);
1052 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed;
break;
1053 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed;
break;
1054 case POINT_CONVERSION_HYBRID: ret = ID_hybrid;
break;
1055 default:
ossl_raise(
eEC_GROUP,
"unsupported point conversion form: %d, this module should be updated", form);
1066 static VALUE ossl_ec_group_set_point_conversion_form(
VALUE self,
VALUE form_v)
1068 EC_GROUP *group =
NULL;
1069 point_conversion_form_t form;
1072 Require_EC_GROUP(
self, group);
1074 if (form_id == ID_uncompressed) {
1075 form = POINT_CONVERSION_UNCOMPRESSED;
1076 }
else if (form_id == ID_compressed) {
1077 form = POINT_CONVERSION_COMPRESSED;
1078 }
else if (form_id == ID_hybrid) {
1079 form = POINT_CONVERSION_HYBRID;
1084 EC_GROUP_set_point_conversion_form(group, form);
1094 static VALUE ossl_ec_group_get_seed(
VALUE self)
1096 EC_GROUP *group =
NULL;
1099 Require_EC_GROUP(
self, group);
1101 seed_len = EC_GROUP_get_seed_len(group);
1106 return rb_str_new((
const char *)EC_GROUP_get0_seed(group), seed_len);
1116 EC_GROUP *group =
NULL;
1118 Require_EC_GROUP(
self, group);
1134 static VALUE ossl_ec_group_get_degree(
VALUE self)
1136 EC_GROUP *group =
NULL;
1138 Require_EC_GROUP(
self, group);
1140 return INT2NUM(EC_GROUP_get_degree(group));
1143 static VALUE ossl_ec_group_to_string(
VALUE self,
int format)
1150 Get_EC_GROUP(
self, group);
1152 if (!(out = BIO_new(BIO_s_mem())))
1157 i = PEM_write_bio_ECPKParameters(out, group);
1160 i = i2d_ECPKParameters_bio(out, group);
1182 static VALUE ossl_ec_group_to_pem(
VALUE self)
1184 return ossl_ec_group_to_string(
self, EXPORT_PEM);
1192 static VALUE ossl_ec_group_to_der(
VALUE self)
1194 return ossl_ec_group_to_string(
self, EXPORT_DER);
1202 static VALUE ossl_ec_group_to_text(
VALUE self)
1208 Require_EC_GROUP(
self, group);
1209 if (!(out = BIO_new(BIO_s_mem()))) {
1212 if (!ECPKParameters_print(out, group, 0)) {
1222 static void ossl_ec_point_free(ossl_ec_point *ec_point)
1224 if (!ec_point->dont_free && ec_point->point)
1225 EC_POINT_clear_free(ec_point->point);
1229 static VALUE ossl_ec_point_alloc(
VALUE klass)
1231 ossl_ec_point *ec_point;
1234 obj =
Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
1247 static VALUE ossl_ec_point_initialize(
int argc,
VALUE *argv,
VALUE self)
1249 ossl_ec_point *ec_point;
1250 EC_POINT *point =
NULL;
1253 const EC_GROUP *group =
NULL;
1256 if (ec_point->point)
1259 switch (
rb_scan_args(argc, argv,
"11", &arg1, &arg2)) {
1262 const EC_POINT *arg_point;
1265 SafeRequire_EC_GROUP(group_v, group);
1266 SafeRequire_EC_POINT(arg1, arg_point);
1268 point = EC_POINT_dup(arg_point, group);
1271 SafeRequire_EC_GROUP(group_v, group);
1273 point = EC_POINT_new(group);
1275 ossl_raise(
eEC_POINT,
"wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1283 SafeRequire_EC_GROUP(group_v, group);
1296 if (point ==
NULL) {
1311 ec_point->point = point;
1326 EC_POINT *point1, *point2;
1329 const EC_GROUP *
group;
1331 if (ossl_ec_group_eql(group_v1, group_v2) ==
Qfalse)
1334 Require_EC_POINT(a, point1);
1335 SafeRequire_EC_POINT(b, point2);
1336 SafeRequire_EC_GROUP(group_v1, group);
1338 if (EC_POINT_cmp(group, point1, point2,
ossl_bn_ctx) == 1)
1349 static VALUE ossl_ec_point_is_at_infinity(
VALUE self)
1353 const EC_GROUP *
group;
1355 Require_EC_POINT(
self, point);
1356 SafeRequire_EC_GROUP(group_v, group);
1358 switch (EC_POINT_is_at_infinity(group, point)) {
1359 case 1:
return Qtrue;
1372 static VALUE ossl_ec_point_is_on_curve(
VALUE self)
1376 const EC_GROUP *
group;
1378 Require_EC_POINT(
self, point);
1379 SafeRequire_EC_GROUP(group_v, group);
1381 switch (EC_POINT_is_on_curve(group, point,
ossl_bn_ctx)) {
1382 case 1:
return Qtrue;
1395 static VALUE ossl_ec_point_make_affine(
VALUE self)
1399 const EC_GROUP *
group;
1401 Require_EC_POINT(
self, point);
1402 SafeRequire_EC_GROUP(group_v, group);
1404 if (EC_POINT_make_affine(group, point,
ossl_bn_ctx) != 1)
1415 static VALUE ossl_ec_point_invert(
VALUE self)
1419 const EC_GROUP *
group;
1421 Require_EC_POINT(
self, point);
1422 SafeRequire_EC_GROUP(group_v, group);
1424 if (EC_POINT_invert(group, point,
ossl_bn_ctx) != 1)
1435 static VALUE ossl_ec_point_set_to_infinity(
VALUE self)
1439 const EC_GROUP *
group;
1441 Require_EC_POINT(
self, point);
1442 SafeRequire_EC_GROUP(group_v, group);
1444 if (EC_POINT_set_to_infinity(group, point) != 1)
1461 const EC_GROUP *
group;
1462 point_conversion_form_t form;
1465 Require_EC_POINT(
self, point);
1466 SafeRequire_EC_GROUP(group_v, group);
1468 form = EC_GROUP_get_point_conversion_form(group);
1488 EC_POINT *point1, *point2;
1489 const EC_GROUP *
group;
1491 VALUE bn_v1, bn_v2,
r, points_v;
1494 Require_EC_POINT(
self, point1);
1495 SafeRequire_EC_GROUP(group_v, group);
1498 ossl_ec_point_initialize(1, &group_v, r);
1499 Require_EC_POINT(r, point2);
1501 argc =
rb_scan_args(argc, argv,
"12", &bn_v1, &points_v, &bn_v2);
1508 if (EC_POINT_mul(group, point2, bn2, point1, bn1,
ossl_bn_ctx) != 1)
1511 size_t i, points_len, bignums_len;
1512 const EC_POINT **points;
1513 const BIGNUM **bignums;
1517 bignums = (
const BIGNUM **)OPENSSL_malloc(bignums_len * (
int)
sizeof(BIGNUM *));
1519 for (i = 0; i < bignums_len; ++
i) {
1524 OPENSSL_free((
void *)bignums);
1530 points = (
const EC_POINT **)OPENSSL_malloc(points_len * (
int)
sizeof(EC_POINT *));
1532 for (i = 0; i < points_len; ++
i) {
1539 if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums,
ossl_bn_ctx) != 1) {
1540 OPENSSL_free((
void *)bignums);
1541 OPENSSL_free((
void *)points);
1544 OPENSSL_free((
void *)bignums);
1545 OPENSSL_free((
void *)points);
1551 static void no_copy(
VALUE klass)
1561 #ifdef DONT_NEED_RDOC_WORKAROUND
1579 s_GF2m_simple =
rb_intern(
"GF2m_simple");
1581 ID_uncompressed =
rb_intern(
"uncompressed");
1582 ID_compressed =
rb_intern(
"compressed");
1585 #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)
rb_funcall(memo->yielder, id_lshift, 1, rb_assoc_new(memo->prev_value, memo->prev_elts))
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_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_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 *)