7 #if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL) 15 #define GetPKeyEC(obj, pkey) do { \ 16 GetPKey((obj), (pkey)); \ 17 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_EC) { \ 18 ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \ 21 #define GetEC(obj, key) do { \ 23 GetPKeyEC(obj, _pkey); \ 24 (key) = EVP_PKEY_get0_EC_KEY(_pkey); \ 26 #define SafeGetEC(obj, key) do { \ 27 OSSL_Check_Kind(obj, cEC); \ 31 #define GetECGroup(obj, group) do { \ 32 TypedData_Get_Struct(obj, EC_GROUP, &ossl_ec_group_type, group); \ 33 if ((group) == NULL) \ 34 ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \ 36 #define SafeGetECGroup(obj, group) do { \ 37 OSSL_Check_Kind((obj), cEC_GROUP); \ 38 GetECGroup(obj, group); \ 41 #define GetECPoint(obj, point) do { \ 42 TypedData_Get_Struct(obj, EC_POINT, &ossl_ec_point_type, point); \ 43 if ((point) == NULL) \ 44 ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \ 46 #define SafeGetECPoint(obj, point) do { \ 47 OSSL_Check_Kind((obj), cEC_POINT); \ 48 GetECPoint(obj, point); \ 50 #define GetECPointGroup(obj, group) do { \ 51 VALUE _group = rb_attr_get(obj, id_i_group); \ 52 SafeGetECGroup(_group, group); \ 63 static ID s_GFp_simple;
67 static ID s_GF2m_simple;
69 static ID ID_uncompressed;
70 static ID ID_compressed;
75 static VALUE ec_group_new(
const EC_GROUP *group);
76 static VALUE ec_point_new(
const EC_POINT *point,
const EC_GROUP *group);
78 static VALUE ec_instance(
VALUE klass, EC_KEY *ec)
87 if (!(pkey = EVP_PKEY_new())) {
90 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
104 obj = ec_instance(
cEC, EC_KEY_new());
124 ec_key_new_from_group(
VALUE arg)
131 SafeGetECGroup(arg, group);
132 if (!(ec = EC_KEY_new()))
135 if (!EC_KEY_set_group(ec, group)) {
142 if (nid == NID_undef)
145 if (!(ec = EC_KEY_new_by_curve_name(nid)))
148 EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
149 EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
163 ossl_ec_key_s_generate(
VALUE klass,
VALUE arg)
168 ec = ec_key_new_from_group(arg);
170 obj = ec_instance(klass, ec);
176 if (!EC_KEY_generate_key(ec))
206 if (!(ec = EC_KEY_new()))
209 EC_KEY *other_ec =
NULL;
211 SafeGetEC(arg, other_ec);
212 if (!(ec = EC_KEY_dup(other_ec)))
215 ec = ec_key_new_from_group(arg);
229 ec = d2i_ECPrivateKey_bio(in,
NULL);
233 ec = d2i_EC_PUBKEY_bio(in,
NULL);
239 ec = ec_key_new_from_group(arg);
243 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
252 ossl_ec_key_initialize_copy(
VALUE self,
VALUE other)
260 SafeGetEC(other, ec);
262 ec_new = EC_KEY_dup(ec);
265 if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) {
281 ossl_ec_key_get_group(
VALUE self)
284 const EC_GROUP *group;
287 group = EC_KEY_get0_group(ec);
291 return ec_group_new(group);
302 ossl_ec_key_set_group(
VALUE self,
VALUE group_v)
308 SafeGetECGroup(group_v, group);
310 if (EC_KEY_set_group(ec, group) != 1)
322 static VALUE ossl_ec_key_get_private_key(
VALUE self)
328 if ((bn = EC_KEY_get0_private_key(ec)) ==
NULL)
340 static VALUE ossl_ec_key_set_private_key(
VALUE self,
VALUE private_key)
346 if (!
NIL_P(private_key))
349 switch (EC_KEY_set_private_key(ec, bn)) {
368 static VALUE ossl_ec_key_get_public_key(
VALUE self)
371 const EC_POINT *point;
374 if ((point = EC_KEY_get0_public_key(ec)) ==
NULL)
377 return ec_point_new(point, EC_KEY_get0_group(ec));
389 EC_POINT *point =
NULL;
392 if (!
NIL_P(public_key))
393 SafeGetECPoint(public_key, point);
395 switch (EC_KEY_set_public_key(ec, point)) {
415 static VALUE ossl_ec_key_is_public(
VALUE self)
421 return EC_KEY_get0_public_key(ec) ?
Qtrue :
Qfalse;
431 static VALUE ossl_ec_key_is_private(
VALUE self)
437 return EC_KEY_get0_private_key(ec) ?
Qtrue :
Qfalse;
447 const EVP_CIPHER *cipher =
NULL;
451 if (EC_KEY_get0_public_key(ec) ==
NULL)
454 if (EC_KEY_check_key(ec) != 1)
457 if (EC_KEY_get0_private_key(ec))
465 if (!(out = BIO_new(BIO_s_mem())))
473 i = PEM_write_bio_EC_PUBKEY(out, ec);
479 i = i2d_ECPrivateKey_bio(out, ec);
481 i = i2d_EC_PUBKEY_bio(out, ec);
512 VALUE cipher, passwd;
514 return ossl_ec_key_to_string(
self, cipher, passwd, EXPORT_PEM);
525 return ossl_ec_key_to_string(
self,
Qnil,
Qnil, EXPORT_DER);
541 if (!(out = BIO_new(BIO_s_mem()))) {
544 if (!EC_KEY_print(out, ec, 0)) {
567 static VALUE ossl_ec_key_generate_key(
VALUE self)
572 if (EC_KEY_generate_key(ec) != 1)
586 static VALUE ossl_ec_key_check_key(
VALUE self)
591 if (EC_KEY_check_key(ec) != 1)
611 SafeGetECPoint(pubkey, point);
617 buf_len = ECDH_compute_key(
RSTRING_PTR(str), buf_len, point, ec,
NULL);
637 unsigned int buf_len;
643 if (EC_KEY_get0_private_key(ec) ==
NULL)
669 case 1:
return Qtrue;
683 ossl_ec_group_free(
void *ptr)
685 EC_GROUP_clear_free(ptr);
691 0, ossl_ec_group_free,
697 ossl_ec_group_alloc(
VALUE klass)
703 ec_group_new(
const EC_GROUP *group)
709 group_new = EC_GROUP_dup(group);
738 static VALUE ossl_ec_group_initialize(
int argc,
VALUE *argv,
VALUE self)
740 VALUE arg1, arg2, arg3, arg4;
747 switch (
rb_scan_args(argc, argv,
"13", &arg1, &arg2, &arg3, &arg4)) {
750 const EC_METHOD *method =
NULL;
753 if (
id == s_GFp_simple) {
754 method = EC_GFp_simple_method();
755 }
else if (
id == s_GFp_mont) {
756 method = EC_GFp_mont_method();
757 }
else if (
id == s_GFp_nist) {
758 method = EC_GFp_nist_method();
759 #if !defined(OPENSSL_NO_EC2M) 760 }
else if (
id == s_GF2m_simple) {
761 method = EC_GF2m_simple_method();
766 if ((group = EC_GROUP_new(method)) ==
NULL)
772 const EC_GROUP *arg1_group;
774 SafeGetECGroup(arg1, arg1_group);
775 if ((group = EC_GROUP_dup(arg1_group)) ==
NULL)
780 group = PEM_read_bio_ECPKParameters(in,
NULL,
NULL,
NULL);
783 group = d2i_ECPKParameters_bio(in,
NULL);
790 int nid = OBJ_sn2nid(name);
793 if (nid == NID_undef)
796 group = EC_GROUP_new_by_curve_name(nid);
800 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
801 EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
809 EC_GROUP *(*new_curve)(
const BIGNUM *,
const BIGNUM *,
const BIGNUM *, BN_CTX *) =
NULL;
815 new_curve = EC_GROUP_new_curve_GFp;
816 #if !defined(OPENSSL_NO_EC2M) 817 }
else if (
id == s_GF2m) {
818 new_curve = EC_GROUP_new_curve_GF2m;
843 ossl_ec_group_initialize_copy(
VALUE self,
VALUE other)
845 EC_GROUP *group, *group_new;
850 SafeGetECGroup(other, group);
852 group_new = EC_GROUP_dup(group);
870 EC_GROUP *group1 =
NULL, *group2 =
NULL;
872 GetECGroup(a, group1);
873 SafeGetECGroup(b, group2);
875 if (EC_GROUP_cmp(group1, group2,
ossl_bn_ctx) == 1)
889 static VALUE ossl_ec_group_get_generator(
VALUE self)
894 GetECGroup(
self, group);
895 generator = EC_GROUP_get0_generator(group);
899 return ec_point_new(generator, group);
913 EC_GROUP *group =
NULL;
914 const EC_POINT *point;
915 const BIGNUM *o, *co;
917 GetECGroup(
self, group);
918 SafeGetECPoint(generator, point);
922 if (EC_GROUP_set_generator(group, point, o, co) != 1)
936 static VALUE ossl_ec_group_get_order(
VALUE self)
940 EC_GROUP *group =
NULL;
942 GetECGroup(
self, group);
947 if (EC_GROUP_get_order(group, bn,
ossl_bn_ctx) != 1)
961 static VALUE ossl_ec_group_get_cofactor(
VALUE self)
965 EC_GROUP *group =
NULL;
967 GetECGroup(
self, group);
972 if (EC_GROUP_get_cofactor(group, bn,
ossl_bn_ctx) != 1)
986 static VALUE ossl_ec_group_get_curve_name(
VALUE self)
988 EC_GROUP *group =
NULL;
991 GetECGroup(
self, group);
995 nid = EC_GROUP_get_curve_name(group);
1010 static VALUE ossl_s_builtin_curves(
VALUE self)
1012 EC_builtin_curve *curves =
NULL;
1017 curves =
ALLOCA_N(EC_builtin_curve, crv_len);
1020 if (!EC_get_builtin_curves(curves, crv_len))
1025 for (n = 0; n < crv_len; n++) {
1026 const char *sname = OBJ_nid2sn(curves[n].nid);
1027 const char *comment = curves[n].comment;
1046 static VALUE ossl_ec_group_get_asn1_flag(
VALUE self)
1048 EC_GROUP *group =
NULL;
1051 GetECGroup(
self, group);
1052 flag = EC_GROUP_get_asn1_flag(group);
1073 EC_GROUP *group =
NULL;
1075 GetECGroup(
self, group);
1076 EC_GROUP_set_asn1_flag(group,
NUM2INT(flag_v));
1089 static VALUE ossl_ec_group_get_point_conversion_form(
VALUE self)
1091 EC_GROUP *group =
NULL;
1092 point_conversion_form_t form;
1095 GetECGroup(
self, group);
1096 form = EC_GROUP_get_point_conversion_form(group);
1099 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed;
break;
1100 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed;
break;
1101 case POINT_CONVERSION_HYBRID: ret = ID_hybrid;
break;
1102 default:
ossl_raise(
eEC_GROUP,
"unsupported point conversion form: %d, this module should be updated", form);
1108 static point_conversion_form_t
1109 parse_point_conversion_form_symbol(
VALUE sym)
1113 if (
id == ID_uncompressed)
1114 return POINT_CONVERSION_UNCOMPRESSED;
1115 else if (
id == ID_compressed)
1116 return POINT_CONVERSION_COMPRESSED;
1117 else if (
id == ID_hybrid)
1118 return POINT_CONVERSION_HYBRID;
1121 " (expected :compressed, :uncompressed, or :hybrid)", sym);
1144 ossl_ec_group_set_point_conversion_form(
VALUE self,
VALUE form_v)
1147 point_conversion_form_t form;
1149 GetECGroup(
self, group);
1150 form = parse_point_conversion_form_symbol(form_v);
1152 EC_GROUP_set_point_conversion_form(group, form);
1163 static VALUE ossl_ec_group_get_seed(
VALUE self)
1165 EC_GROUP *group =
NULL;
1168 GetECGroup(
self, group);
1169 seed_len = EC_GROUP_get_seed_len(group);
1174 return rb_str_new((
const char *)EC_GROUP_get0_seed(group), seed_len);
1185 EC_GROUP *group =
NULL;
1187 GetECGroup(
self, group);
1204 static VALUE ossl_ec_group_get_degree(
VALUE self)
1206 EC_GROUP *group =
NULL;
1208 GetECGroup(
self, group);
1210 return INT2NUM(EC_GROUP_get_degree(group));
1213 static VALUE ossl_ec_group_to_string(
VALUE self,
int format)
1220 GetECGroup(
self, group);
1222 if (!(out = BIO_new(BIO_s_mem())))
1227 i = PEM_write_bio_ECPKParameters(out, group);
1230 i = i2d_ECPKParameters_bio(out, group);
1253 static VALUE ossl_ec_group_to_pem(
VALUE self)
1255 return ossl_ec_group_to_string(
self, EXPORT_PEM);
1264 static VALUE ossl_ec_group_to_der(
VALUE self)
1266 return ossl_ec_group_to_string(
self, EXPORT_DER);
1275 static VALUE ossl_ec_group_to_text(
VALUE self)
1281 GetECGroup(
self, group);
1282 if (!(out = BIO_new(BIO_s_mem()))) {
1285 if (!ECPKParameters_print(out, group, 0)) {
1299 ossl_ec_point_free(
void *ptr)
1301 EC_POINT_clear_free(ptr);
1307 0, ossl_ec_point_free,
1313 ossl_ec_point_alloc(
VALUE klass)
1319 ec_point_new(
const EC_POINT *point,
const EC_GROUP *group)
1321 EC_POINT *point_new;
1325 point_new = EC_POINT_dup(point, group);
1329 rb_ivar_set(obj, id_i_group, ec_group_new(group));
1342 static VALUE ossl_ec_point_initialize(
int argc,
VALUE *argv,
VALUE self)
1347 const EC_GROUP *group =
NULL;
1353 switch (
rb_scan_args(argc, argv,
"11", &arg1, &arg2)) {
1356 const EC_POINT *arg_point;
1359 SafeGetECGroup(group_v, group);
1360 SafeGetECPoint(arg1, arg_point);
1362 point = EC_POINT_dup(arg_point, group);
1365 SafeGetECGroup(group_v, group);
1367 point = EC_POINT_new(group);
1369 ossl_raise(
eEC_POINT,
"wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
1377 SafeGetECGroup(group_v, group);
1390 if (point ==
NULL) {
1412 ossl_ec_point_initialize_copy(
VALUE self,
VALUE other)
1414 EC_POINT *point, *point_new;
1421 SafeGetECPoint(other, point);
1424 SafeGetECGroup(group_v, group);
1426 point_new = EC_POINT_dup(point, group);
1442 EC_POINT *point1, *point2;
1445 const EC_GROUP *group;
1447 if (ossl_ec_group_eql(group_v1, group_v2) ==
Qfalse)
1450 GetECPoint(a, point1);
1451 SafeGetECPoint(b, point2);
1452 SafeGetECGroup(group_v1, group);
1454 if (EC_POINT_cmp(group, point1, point2,
ossl_bn_ctx) == 1)
1464 static VALUE ossl_ec_point_is_at_infinity(
VALUE self)
1467 const EC_GROUP *group;
1469 GetECPoint(
self, point);
1470 GetECPointGroup(
self, group);
1472 switch (EC_POINT_is_at_infinity(group, point)) {
1473 case 1:
return Qtrue;
1485 static VALUE ossl_ec_point_is_on_curve(
VALUE self)
1488 const EC_GROUP *group;
1490 GetECPoint(
self, point);
1491 GetECPointGroup(
self, group);
1493 switch (EC_POINT_is_on_curve(group, point,
ossl_bn_ctx)) {
1494 case 1:
return Qtrue;
1506 static VALUE ossl_ec_point_make_affine(
VALUE self)
1509 const EC_GROUP *group;
1511 GetECPoint(
self, point);
1512 GetECPointGroup(
self, group);
1514 if (EC_POINT_make_affine(group, point,
ossl_bn_ctx) != 1)
1524 static VALUE ossl_ec_point_invert(
VALUE self)
1527 const EC_GROUP *group;
1529 GetECPoint(
self, point);
1530 GetECPointGroup(
self, group);
1532 if (EC_POINT_invert(group, point,
ossl_bn_ctx) != 1)
1542 static VALUE ossl_ec_point_set_to_infinity(
VALUE self)
1545 const EC_GROUP *group;
1547 GetECPoint(
self, point);
1548 GetECPointGroup(
self, group);
1550 if (EC_POINT_set_to_infinity(group, point) != 1)
1567 ossl_ec_point_to_bn(
int argc,
VALUE *argv,
VALUE self)
1570 VALUE form_obj, bn_obj;
1571 const EC_GROUP *group;
1572 point_conversion_form_t form;
1575 GetECPoint(
self, point);
1576 GetECPointGroup(
self, group);
1578 if (
NIL_P(form_obj))
1579 form = EC_GROUP_get_point_conversion_form(group);
1581 form = parse_point_conversion_form_symbol(form_obj);
1611 EC_POINT *point_self, *point_result;
1612 const EC_GROUP *group;
1615 const BIGNUM *bn_g =
NULL;
1617 GetECPoint(
self, point_self);
1618 SafeGetECGroup(group_v, group);
1621 ossl_ec_point_initialize(1, &group_v, result);
1622 GetECPoint(result, point_result);
1630 if (EC_POINT_mul(group, point_result, bn_g, point_self, bn,
ossl_bn_ctx) != 1)
1638 VALUE bns_tmp, tmp_p, tmp_b;
1639 const EC_POINT **points;
1640 const BIGNUM **bignums;
1649 bignums =
ALLOCV_N(
const BIGNUM *, tmp_b, num);
1650 for (i = 0; i < num; i++) {
1656 points =
ALLOCV_N(
const EC_POINT *, tmp_p, num);
1657 points[0] = point_self;
1658 for (i = 0; i < num - 1; i++)
1659 SafeGetECPoint(
RARRAY_AREF(arg2, i), points[i + 1]);
1664 if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums,
ossl_bn_ctx) != 1) {
1714 s_GF2m_simple =
rb_intern(
"GF2m_simple");
1716 ID_uncompressed =
rb_intern(
"uncompressed");
1717 ID_compressed =
rb_intern(
"compressed");
1721 #if defined(OPENSSL_EC_EXPLICIT_CURVE)
#define RUBY_TYPED_FREE_IMMEDIATELY
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
#define SetPKey(obj, pkey)
#define TypedData_Wrap_Struct(klass, data_type, sval)
#define TypedData_Get_Struct(obj, type, data_type, sval)
VALUE rb_ary_push(VALUE ary, VALUE item)
VALUE rb_ary_tmp_new(long capa)
BIO * ossl_obj2bio(volatile VALUE *pobj)
void rb_str_set_len(VALUE, long)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
#define GetPKey(obj, pkey)
VALUE ossl_membio2str(BIO *bio)
#define RB_TYPE_P(obj, type)
#define rb_define_copy_func(klass, func)
void ossl_clear_error(void)
RUBY_EXTERN VALUE rb_cObject
void rb_attr(VALUE, ID, int, int, int)
#define OSSL_BIO_reset(bio)
void rb_define_const(VALUE, const char *, VALUE)
#define ALLOCV_N(type, v, n)
#define ALLOCA_N(type, n)
VALUE rb_obj_alloc(VALUE)
const EVP_CIPHER * GetCipherPtr(VALUE obj)
VALUE rb_str_resize(VALUE, long)
int ossl_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd_)
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_ivar_set(VALUE, ID, VALUE)
VALUE ossl_pem_passwd_value(VALUE pass)
VALUE rb_define_module_under(VALUE outer, const char *name)
#define StringValueCStr(v)
#define RARRAY_AREF(a, i)
void ossl_raise(VALUE exc, const char *fmt,...)
VALUE ossl_bn_new(const BIGNUM *bn)
#define RTYPEDDATA_DATA(v)
#define EVP_PKEY_base_id(pkey)
#define RSTRING_LENINT(str)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE ossl_ec_new(EVP_PKEY *)
VALUE rb_attr_get(VALUE, ID)
VALUE rb_str_new(const char *, long)