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;
109 static VALUE ec_instance(
VALUE klass, EC_KEY *ec)
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) {
171 ossl_raise(eECError,
"EC_KEY already initialized");
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)
214 ossl_raise(eECError,
"unknown curve name (%s)\n", name);
216 if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
217 ossl_raise(eECError,
"unable to create curve (%s)\n", name);
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)) {
230 ossl_raise(eECError,
"EVP_PKEY_assign_EC_KEY");
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)) {
358 ossl_raise(eECError,
"EC_KEY_set_private_key");
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)
403 ossl_raise(eECError,
"EC_KEY_get0_get0_group (has public_key but no group???");
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)) {
430 ossl_raise(eECError,
"EC_KEY_set_public_key");
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)
478 ossl_raise(eECError,
"can't export - no public key set");
480 if (EC_KEY_check_key(ec) != 1)
481 ossl_raise(eECError,
"can't export - EC_KEY_check_key failed");
483 if (EC_KEY_get0_private_key(ec))
486 if (!(out = BIO_new(BIO_s_mem())))
492 const EVP_CIPHER *cipher;
502 i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
504 i = PEM_write_bio_EC_PUBKEY(out, ec);
510 i = i2d_ECPrivateKey_bio(out, ec);
512 i = i2d_EC_PUBKEY_bio(out, ec);
545 VALUE cipher, passwd;
547 return ossl_ec_key_to_string(
self, cipher, passwd, EXPORT_PEM);
558 return ossl_ec_key_to_string(
self,
Qnil,
Qnil, EXPORT_DER);
573 Require_EC_KEY(
self, ec);
574 if (!(out = BIO_new(BIO_s_mem()))) {
577 if (!EC_KEY_print(out, ec, 0)) {
592 static VALUE ossl_ec_key_generate_key(
VALUE self)
596 Require_EC_KEY(
self, ec);
598 if (EC_KEY_generate_key(ec) != 1)
612 static VALUE ossl_ec_key_check_key(
VALUE self)
616 Require_EC_KEY(
self, ec);
618 if (EC_KEY_check_key(ec) != 1)
637 Require_EC_KEY(
self, ec);
638 SafeRequire_EC_POINT(pubkey, point);
644 buf_len = ECDH_compute_key(
RSTRING_PTR(str), buf_len, point, ec, NULL);
664 unsigned int buf_len;
667 Require_EC_KEY(
self, ec);
670 if (EC_KEY_get0_private_key(ec) == NULL)
671 ossl_raise(eECError,
"Private EC key needed!");
692 Require_EC_KEY(
self, ec);
697 case 1:
return Qtrue;
705 static void ossl_ec_group_free(ossl_ec_group *ec_group)
707 if (!ec_group->dont_free && ec_group->group)
708 EC_GROUP_clear_free(ec_group->group);
714 ossl_ec_group *ec_group;
717 obj =
Data_Make_Struct(klass, ossl_ec_group, 0, ossl_ec_group_free, ec_group);
738 static VALUE ossl_ec_group_initialize(
int argc,
VALUE *argv,
VALUE self)
740 VALUE arg1, arg2, arg3, arg4;
741 ossl_ec_group *ec_group;
742 EC_GROUP *group =
NULL;
745 if (ec_group->group != NULL)
748 switch (
rb_scan_args(argc, argv,
"13", &arg1, &arg2, &arg3, &arg4)) {
751 const EC_METHOD *method =
NULL;
754 if (
id == s_GFp_simple) {
755 method = EC_GFp_simple_method();
756 }
else if (
id == s_GFp_mont) {
757 method = EC_GFp_mont_method();
758 }
else if (
id == s_GFp_nist) {
759 method = EC_GFp_nist_method();
760 }
else if (
id == s_GF2m_simple) {
761 method = EC_GF2m_simple_method();
765 if ((group = EC_GROUP_new(method)) == NULL)
771 const EC_GROUP *arg1_group;
773 SafeRequire_EC_GROUP(arg1, arg1_group);
774 if ((group = EC_GROUP_dup(arg1_group)) == NULL)
779 group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
782 group = d2i_ECPKParameters_bio(in, NULL);
789 int nid = OBJ_sn2nid(name);
791 (void)ERR_get_error();
792 if (nid == NID_undef)
793 ossl_raise(eEC_GROUP,
"unknown curve name (%s)", name);
795 group = EC_GROUP_new_by_curve_name(nid);
797 ossl_raise(eEC_GROUP,
"unable to create curve (%s)", name);
799 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
800 EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
808 EC_GROUP *(*new_curve)(
const BIGNUM *,
const BIGNUM *,
const BIGNUM *, BN_CTX *) = NULL;
814 new_curve = EC_GROUP_new_curve_GFp;
815 }
else if (
id == s_GF2m) {
816 new_curve = EC_GROUP_new_curve_GF2m;
821 if ((group = new_curve(p, a, b,
ossl_bn_ctx)) == NULL)
835 ec_group->group = group;
846 EC_GROUP *group1 =
NULL, *group2 =
NULL;
848 Require_EC_GROUP(a, group1);
849 SafeRequire_EC_GROUP(b, group2);
851 if (EC_GROUP_cmp(group1, group2,
ossl_bn_ctx) == 1)
862 static VALUE ossl_ec_group_get_generator(
VALUE self)
865 EC_GROUP *group =
NULL;
867 Require_EC_GROUP(
self, group);
869 point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group),
self);
881 EC_GROUP *group =
NULL;
882 const EC_POINT *point;
883 const BIGNUM *o, *co;
885 Require_EC_GROUP(
self, group);
886 SafeRequire_EC_POINT(generator, point);
890 if (EC_GROUP_set_generator(group, point, o, co) != 1)
891 ossl_raise(eEC_GROUP,
"EC_GROUP_set_generator");
901 static VALUE ossl_ec_group_get_order(
VALUE self)
905 EC_GROUP *group =
NULL;
907 Require_EC_GROUP(
self, group);
912 if (EC_GROUP_get_order(group, bn,
ossl_bn_ctx) != 1)
923 static VALUE ossl_ec_group_get_cofactor(
VALUE self)
927 EC_GROUP *group =
NULL;
929 Require_EC_GROUP(
self, group);
934 if (EC_GROUP_get_cofactor(group, bn,
ossl_bn_ctx) != 1)
935 ossl_raise(eEC_GROUP,
"EC_GROUP_get_cofactor");
945 static VALUE ossl_ec_group_get_curve_name(
VALUE self)
947 EC_GROUP *group =
NULL;
950 Get_EC_GROUP(
self, group);
954 nid = EC_GROUP_get_curve_name(group);
965 static VALUE ossl_s_builtin_curves(
VALUE self)
967 EC_builtin_curve *curves =
NULL;
969 int crv_len =
rb_long2int(EC_get_builtin_curves(NULL, 0));
972 curves =
ALLOCA_N(EC_builtin_curve, crv_len);
975 if (!EC_get_builtin_curves(curves, crv_len))
980 for (n = 0; n < crv_len; n++) {
981 const char *sname = OBJ_nid2sn(curves[n].nid);
982 const char *comment = curves[n].comment;
998 static VALUE ossl_ec_group_get_asn1_flag(
VALUE self)
1000 EC_GROUP *group =
NULL;
1003 Require_EC_GROUP(
self, group);
1005 flag = EC_GROUP_get_asn1_flag(group);
1017 EC_GROUP *group =
NULL;
1019 Require_EC_GROUP(
self, group);
1021 EC_GROUP_set_asn1_flag(group,
NUM2INT(flag_v));
1031 static VALUE ossl_ec_group_get_point_conversion_form(
VALUE self)
1033 EC_GROUP *group =
NULL;
1034 point_conversion_form_t form;
1037 Require_EC_GROUP(
self, group);
1039 form = EC_GROUP_get_point_conversion_form(group);
1042 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed;
break;
1043 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed;
break;
1044 case POINT_CONVERSION_HYBRID: ret = ID_hybrid;
break;
1045 default:
ossl_raise(eEC_GROUP,
"unsupported point conversion form: %d, this module should be updated", form);
1056 static VALUE ossl_ec_group_set_point_conversion_form(
VALUE self,
VALUE form_v)
1058 EC_GROUP *group =
NULL;
1059 point_conversion_form_t form;
1062 Require_EC_GROUP(
self, group);
1064 if (form_id == ID_uncompressed) {
1065 form = POINT_CONVERSION_UNCOMPRESSED;
1066 }
else if (form_id == ID_compressed) {
1067 form = POINT_CONVERSION_COMPRESSED;
1068 }
else if (form_id == ID_hybrid) {
1069 form = POINT_CONVERSION_HYBRID;
1074 EC_GROUP_set_point_conversion_form(group, form);
1084 static VALUE ossl_ec_group_get_seed(
VALUE self)
1086 EC_GROUP *group =
NULL;
1089 Require_EC_GROUP(
self, group);
1091 seed_len = EC_GROUP_get_seed_len(group);
1096 return rb_str_new((
const char *)EC_GROUP_get0_seed(group), seed_len);
1106 EC_GROUP *group =
NULL;
1108 Require_EC_GROUP(
self, group);
1124 static VALUE ossl_ec_group_get_degree(
VALUE self)
1126 EC_GROUP *group =
NULL;
1128 Require_EC_GROUP(
self, group);
1130 return INT2NUM(EC_GROUP_get_degree(group));
1133 static VALUE ossl_ec_group_to_string(
VALUE self,
int format)
1140 Get_EC_GROUP(
self, group);
1142 if (!(out = BIO_new(BIO_s_mem())))
1143 ossl_raise(eEC_GROUP,
"BIO_new(BIO_s_mem())");
1147 i = PEM_write_bio_ECPKParameters(out, group);
1150 i = i2d_ECPKParameters_bio(out, group);
1172 static VALUE ossl_ec_group_to_pem(
VALUE self)
1174 return ossl_ec_group_to_string(
self, EXPORT_PEM);
1182 static VALUE ossl_ec_group_to_der(
VALUE self)
1184 return ossl_ec_group_to_string(
self, EXPORT_DER);
1192 static VALUE ossl_ec_group_to_text(
VALUE self)
1198 Require_EC_GROUP(
self, group);
1199 if (!(out = BIO_new(BIO_s_mem()))) {
1200 ossl_raise(eEC_GROUP,
"BIO_new(BIO_s_mem())");
1202 if (!ECPKParameters_print(out, group, 0)) {
1212 static void ossl_ec_point_free(ossl_ec_point *ec_point)
1214 if (!ec_point->dont_free && ec_point->point)
1215 EC_POINT_clear_free(ec_point->point);
1219 static VALUE ossl_ec_point_alloc(
VALUE klass)
1221 ossl_ec_point *ec_point;
1224 obj =
Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
1237 static VALUE ossl_ec_point_initialize(
int argc,
VALUE *argv,
VALUE self)
1239 ossl_ec_point *ec_point;
1240 EC_POINT *point =
NULL;
1243 const EC_GROUP *group =
NULL;
1246 if (ec_point->point)
1247 ossl_raise(eEC_POINT,
"EC_POINT already initialized");
1249 switch (
rb_scan_args(argc, argv,
"11", &arg1, &arg2)) {
1252 const EC_POINT *arg_point;
1255 SafeRequire_EC_GROUP(group_v, group);
1256 SafeRequire_EC_POINT(arg1, arg_point);
1258 point = EC_POINT_dup(arg_point, group);
1261 SafeRequire_EC_GROUP(group_v, group);
1263 point = EC_POINT_new(group);
1265 ossl_raise(eEC_POINT,
"wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1273 SafeRequire_EC_GROUP(group_v, group);
1278 point = EC_POINT_bn2point(group, bn, NULL,
ossl_bn_ctx);
1286 if (point == NULL) {
1287 ossl_raise(eEC_POINT,
"unknown type for 2nd arg");
1301 ec_point->point = point;
1315 EC_POINT *point1, *point2;
1318 const EC_GROUP *group;
1320 if (ossl_ec_group_eql(group_v1, group_v2) ==
Qfalse)
1323 Require_EC_POINT(a, point1);
1324 SafeRequire_EC_POINT(b, point2);
1325 SafeRequire_EC_GROUP(group_v1, group);
1327 if (EC_POINT_cmp(group, point1, point2,
ossl_bn_ctx) == 1)
1338 static VALUE ossl_ec_point_is_at_infinity(
VALUE self)
1342 const EC_GROUP *group;
1344 Require_EC_POINT(
self, point);
1345 SafeRequire_EC_GROUP(group_v, group);
1347 switch (EC_POINT_is_at_infinity(group, point)) {
1348 case 1:
return Qtrue;
1350 default:
ossl_raise(cEC_POINT,
"EC_POINT_is_at_infinity");
1359 static VALUE ossl_ec_point_is_on_curve(
VALUE self)
1363 const EC_GROUP *group;
1365 Require_EC_POINT(
self, point);
1366 SafeRequire_EC_GROUP(group_v, group);
1368 switch (EC_POINT_is_on_curve(group, point,
ossl_bn_ctx)) {
1369 case 1:
return Qtrue;
1371 default:
ossl_raise(cEC_POINT,
"EC_POINT_is_on_curve");
1380 static VALUE ossl_ec_point_make_affine(
VALUE self)
1384 const EC_GROUP *group;
1386 Require_EC_POINT(
self, point);
1387 SafeRequire_EC_GROUP(group_v, group);
1389 if (EC_POINT_make_affine(group, point,
ossl_bn_ctx) != 1)
1390 ossl_raise(cEC_POINT,
"EC_POINT_make_affine");
1400 static VALUE ossl_ec_point_invert(
VALUE self)
1404 const EC_GROUP *group;
1406 Require_EC_POINT(
self, point);
1407 SafeRequire_EC_GROUP(group_v, group);
1409 if (EC_POINT_invert(group, point,
ossl_bn_ctx) != 1)
1420 static VALUE ossl_ec_point_set_to_infinity(
VALUE self)
1424 const EC_GROUP *group;
1426 Require_EC_POINT(
self, point);
1427 SafeRequire_EC_GROUP(group_v, group);
1429 if (EC_POINT_set_to_infinity(group, point) != 1)
1430 ossl_raise(cEC_POINT,
"EC_POINT_set_to_infinity");
1446 const EC_GROUP *group;
1447 point_conversion_form_t form;
1450 Require_EC_POINT(
self, point);
1451 SafeRequire_EC_GROUP(group_v, group);
1453 form = EC_GROUP_get_point_conversion_form(group);
1458 if (EC_POINT_point2bn(group, point, form, bn,
ossl_bn_ctx) == NULL)
1464 static void no_copy(
VALUE klass)
1474 #ifdef DONT_NEED_RDOC_WORKAROUND
1492 s_GF2m_simple =
rb_intern(
"GF2m_simple");
1494 ID_uncompressed =
rb_intern(
"uncompressed");
1495 ID_compressed =
rb_intern(
"compressed");
1498 #ifdef OPENSSL_EC_NAMED_CURVE
1542 rb_define_method(cEC_GROUP,
"set_generator", ossl_ec_group_set_generator, 3);
1546 rb_define_method(cEC_GROUP,
"curve_name", ossl_ec_group_get_curve_name, 0);
1552 rb_define_method(cEC_GROUP,
"point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
1553 rb_define_method(cEC_GROUP,
"point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
1580 rb_define_method(cEC_POINT,
"set_to_infinity!", ossl_ec_point_set_to_infinity, 0);