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 #if !defined(OPENSSL_NO_EC2M)
761 }
else if (
id == s_GF2m_simple) {
762 method = EC_GF2m_simple_method();
767 if ((group = EC_GROUP_new(method)) == NULL)
773 const EC_GROUP *arg1_group;
775 SafeRequire_EC_GROUP(arg1, arg1_group);
776 if ((group = EC_GROUP_dup(arg1_group)) == NULL)
781 group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
784 group = d2i_ECPKParameters_bio(in, NULL);
791 int nid = OBJ_sn2nid(name);
793 (void)ERR_get_error();
794 if (nid == NID_undef)
795 ossl_raise(eEC_GROUP,
"unknown curve name (%s)", name);
797 group = EC_GROUP_new_by_curve_name(nid);
799 ossl_raise(eEC_GROUP,
"unable to create curve (%s)", name);
801 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
802 EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
810 EC_GROUP *(*new_curve)(
const BIGNUM *,
const BIGNUM *,
const BIGNUM *, BN_CTX *) = NULL;
816 new_curve = EC_GROUP_new_curve_GFp;
817 #if !defined(OPENSSL_NO_EC2M)
818 }
else if (
id == s_GF2m) {
819 new_curve = EC_GROUP_new_curve_GF2m;
825 if ((group = new_curve(p, a, b,
ossl_bn_ctx)) == NULL)
839 ec_group->group = group;
850 EC_GROUP *group1 =
NULL, *group2 =
NULL;
852 Require_EC_GROUP(a, group1);
853 SafeRequire_EC_GROUP(b, group2);
855 if (EC_GROUP_cmp(group1, group2,
ossl_bn_ctx) == 1)
866 static VALUE ossl_ec_group_get_generator(
VALUE self)
869 EC_GROUP *group =
NULL;
871 Require_EC_GROUP(
self, group);
873 point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group),
self);
885 EC_GROUP *group =
NULL;
886 const EC_POINT *point;
887 const BIGNUM *o, *co;
889 Require_EC_GROUP(
self, group);
890 SafeRequire_EC_POINT(generator, point);
894 if (EC_GROUP_set_generator(group, point, o, co) != 1)
895 ossl_raise(eEC_GROUP,
"EC_GROUP_set_generator");
905 static VALUE ossl_ec_group_get_order(
VALUE self)
909 EC_GROUP *group =
NULL;
911 Require_EC_GROUP(
self, group);
916 if (EC_GROUP_get_order(group, bn,
ossl_bn_ctx) != 1)
927 static VALUE ossl_ec_group_get_cofactor(
VALUE self)
931 EC_GROUP *group =
NULL;
933 Require_EC_GROUP(
self, group);
938 if (EC_GROUP_get_cofactor(group, bn,
ossl_bn_ctx) != 1)
939 ossl_raise(eEC_GROUP,
"EC_GROUP_get_cofactor");
949 static VALUE ossl_ec_group_get_curve_name(
VALUE self)
951 EC_GROUP *group =
NULL;
954 Get_EC_GROUP(
self, group);
958 nid = EC_GROUP_get_curve_name(group);
969 static VALUE ossl_s_builtin_curves(
VALUE self)
971 EC_builtin_curve *curves =
NULL;
973 int crv_len =
rb_long2int(EC_get_builtin_curves(NULL, 0));
976 curves =
ALLOCA_N(EC_builtin_curve, crv_len);
979 if (!EC_get_builtin_curves(curves, crv_len))
984 for (n = 0; n < crv_len; n++) {
985 const char *sname = OBJ_nid2sn(curves[n].nid);
986 const char *comment = curves[n].comment;
1002 static VALUE ossl_ec_group_get_asn1_flag(
VALUE self)
1004 EC_GROUP *group =
NULL;
1007 Require_EC_GROUP(
self, group);
1009 flag = EC_GROUP_get_asn1_flag(group);
1021 EC_GROUP *group =
NULL;
1023 Require_EC_GROUP(
self, group);
1025 EC_GROUP_set_asn1_flag(group,
NUM2INT(flag_v));
1035 static VALUE ossl_ec_group_get_point_conversion_form(
VALUE self)
1037 EC_GROUP *group =
NULL;
1038 point_conversion_form_t form;
1041 Require_EC_GROUP(
self, group);
1043 form = EC_GROUP_get_point_conversion_form(group);
1046 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed;
break;
1047 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed;
break;
1048 case POINT_CONVERSION_HYBRID: ret = ID_hybrid;
break;
1049 default:
ossl_raise(eEC_GROUP,
"unsupported point conversion form: %d, this module should be updated", form);
1060 static VALUE ossl_ec_group_set_point_conversion_form(
VALUE self,
VALUE form_v)
1062 EC_GROUP *group =
NULL;
1063 point_conversion_form_t form;
1066 Require_EC_GROUP(
self, group);
1068 if (form_id == ID_uncompressed) {
1069 form = POINT_CONVERSION_UNCOMPRESSED;
1070 }
else if (form_id == ID_compressed) {
1071 form = POINT_CONVERSION_COMPRESSED;
1072 }
else if (form_id == ID_hybrid) {
1073 form = POINT_CONVERSION_HYBRID;
1078 EC_GROUP_set_point_conversion_form(group, form);
1088 static VALUE ossl_ec_group_get_seed(
VALUE self)
1090 EC_GROUP *group =
NULL;
1093 Require_EC_GROUP(
self, group);
1095 seed_len = EC_GROUP_get_seed_len(group);
1100 return rb_str_new((
const char *)EC_GROUP_get0_seed(group), seed_len);
1110 EC_GROUP *group =
NULL;
1112 Require_EC_GROUP(
self, group);
1128 static VALUE ossl_ec_group_get_degree(
VALUE self)
1130 EC_GROUP *group =
NULL;
1132 Require_EC_GROUP(
self, group);
1134 return INT2NUM(EC_GROUP_get_degree(group));
1137 static VALUE ossl_ec_group_to_string(
VALUE self,
int format)
1144 Get_EC_GROUP(
self, group);
1146 if (!(out = BIO_new(BIO_s_mem())))
1147 ossl_raise(eEC_GROUP,
"BIO_new(BIO_s_mem())");
1151 i = PEM_write_bio_ECPKParameters(out, group);
1154 i = i2d_ECPKParameters_bio(out, group);
1176 static VALUE ossl_ec_group_to_pem(
VALUE self)
1178 return ossl_ec_group_to_string(
self, EXPORT_PEM);
1186 static VALUE ossl_ec_group_to_der(
VALUE self)
1188 return ossl_ec_group_to_string(
self, EXPORT_DER);
1196 static VALUE ossl_ec_group_to_text(
VALUE self)
1202 Require_EC_GROUP(
self, group);
1203 if (!(out = BIO_new(BIO_s_mem()))) {
1204 ossl_raise(eEC_GROUP,
"BIO_new(BIO_s_mem())");
1206 if (!ECPKParameters_print(out, group, 0)) {
1216 static void ossl_ec_point_free(ossl_ec_point *ec_point)
1218 if (!ec_point->dont_free && ec_point->point)
1219 EC_POINT_clear_free(ec_point->point);
1223 static VALUE ossl_ec_point_alloc(
VALUE klass)
1225 ossl_ec_point *ec_point;
1228 obj =
Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
1241 static VALUE ossl_ec_point_initialize(
int argc,
VALUE *argv,
VALUE self)
1243 ossl_ec_point *ec_point;
1244 EC_POINT *point =
NULL;
1247 const EC_GROUP *group =
NULL;
1250 if (ec_point->point)
1251 ossl_raise(eEC_POINT,
"EC_POINT already initialized");
1253 switch (
rb_scan_args(argc, argv,
"11", &arg1, &arg2)) {
1256 const EC_POINT *arg_point;
1259 SafeRequire_EC_GROUP(group_v, group);
1260 SafeRequire_EC_POINT(arg1, arg_point);
1262 point = EC_POINT_dup(arg_point, group);
1265 SafeRequire_EC_GROUP(group_v, group);
1267 point = EC_POINT_new(group);
1269 ossl_raise(eEC_POINT,
"wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1277 SafeRequire_EC_GROUP(group_v, group);
1282 point = EC_POINT_bn2point(group, bn, NULL,
ossl_bn_ctx);
1290 if (point == NULL) {
1291 ossl_raise(eEC_POINT,
"unknown type for 2nd arg");
1305 ec_point->point = point;
1319 EC_POINT *point1, *point2;
1322 const EC_GROUP *group;
1324 if (ossl_ec_group_eql(group_v1, group_v2) ==
Qfalse)
1327 Require_EC_POINT(a, point1);
1328 SafeRequire_EC_POINT(b, point2);
1329 SafeRequire_EC_GROUP(group_v1, group);
1331 if (EC_POINT_cmp(group, point1, point2,
ossl_bn_ctx) == 1)
1342 static VALUE ossl_ec_point_is_at_infinity(
VALUE self)
1346 const EC_GROUP *group;
1348 Require_EC_POINT(
self, point);
1349 SafeRequire_EC_GROUP(group_v, group);
1351 switch (EC_POINT_is_at_infinity(group, point)) {
1352 case 1:
return Qtrue;
1354 default:
ossl_raise(cEC_POINT,
"EC_POINT_is_at_infinity");
1363 static VALUE ossl_ec_point_is_on_curve(
VALUE self)
1367 const EC_GROUP *group;
1369 Require_EC_POINT(
self, point);
1370 SafeRequire_EC_GROUP(group_v, group);
1372 switch (EC_POINT_is_on_curve(group, point,
ossl_bn_ctx)) {
1373 case 1:
return Qtrue;
1375 default:
ossl_raise(cEC_POINT,
"EC_POINT_is_on_curve");
1384 static VALUE ossl_ec_point_make_affine(
VALUE self)
1388 const EC_GROUP *group;
1390 Require_EC_POINT(
self, point);
1391 SafeRequire_EC_GROUP(group_v, group);
1393 if (EC_POINT_make_affine(group, point,
ossl_bn_ctx) != 1)
1394 ossl_raise(cEC_POINT,
"EC_POINT_make_affine");
1404 static VALUE ossl_ec_point_invert(
VALUE self)
1408 const EC_GROUP *group;
1410 Require_EC_POINT(
self, point);
1411 SafeRequire_EC_GROUP(group_v, group);
1413 if (EC_POINT_invert(group, point,
ossl_bn_ctx) != 1)
1424 static VALUE ossl_ec_point_set_to_infinity(
VALUE self)
1428 const EC_GROUP *group;
1430 Require_EC_POINT(
self, point);
1431 SafeRequire_EC_GROUP(group_v, group);
1433 if (EC_POINT_set_to_infinity(group, point) != 1)
1434 ossl_raise(cEC_POINT,
"EC_POINT_set_to_infinity");
1450 const EC_GROUP *group;
1451 point_conversion_form_t form;
1454 Require_EC_POINT(
self, point);
1455 SafeRequire_EC_GROUP(group_v, group);
1457 form = EC_GROUP_get_point_conversion_form(group);
1462 if (EC_POINT_point2bn(group, point, form, bn,
ossl_bn_ctx) == NULL)
1468 static void no_copy(
VALUE klass)
1478 #ifdef DONT_NEED_RDOC_WORKAROUND
1496 s_GF2m_simple =
rb_intern(
"GF2m_simple");
1498 ID_uncompressed =
rb_intern(
"uncompressed");
1499 ID_compressed =
rb_intern(
"compressed");
1502 #ifdef OPENSSL_EC_NAMED_CURVE
1546 rb_define_method(cEC_GROUP,
"set_generator", ossl_ec_group_set_generator, 3);
1550 rb_define_method(cEC_GROUP,
"curve_name", ossl_ec_group_get_curve_name, 0);
1556 rb_define_method(cEC_GROUP,
"point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
1557 rb_define_method(cEC_GROUP,
"point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
1584 rb_define_method(cEC_POINT,
"set_to_infinity!", ossl_ec_point_set_to_infinity, 0);