00001
00002
00003
00004
00005 #include "ossl.h"
00006
00007 #if !defined(OPENSSL_NO_EC) && (OPENSSL_VERSION_NUMBER >= 0x0090802fL)
00008
00009 typedef struct {
00010 EC_GROUP *group;
00011 int dont_free;
00012 } ossl_ec_group;
00013
00014 typedef struct {
00015 EC_POINT *point;
00016 int dont_free;
00017 } ossl_ec_point;
00018
00019
00020 #define EXPORT_PEM 0
00021 #define EXPORT_DER 1
00022
00023
00024 #define GetPKeyEC(obj, pkey) do { \
00025 GetPKey((obj), (pkey)); \
00026 if (EVP_PKEY_type((pkey)->type) != EVP_PKEY_EC) { \
00027 ossl_raise(rb_eRuntimeError, "THIS IS NOT A EC PKEY!"); \
00028 } \
00029 } while (0)
00030
00031 #define SafeGet_ec_group(obj, group) do { \
00032 OSSL_Check_Kind((obj), cEC_GROUP); \
00033 Data_Get_Struct((obj), ossl_ec_group, (group)); \
00034 } while(0)
00035
00036 #define Get_EC_KEY(obj, key) do { \
00037 EVP_PKEY *pkey; \
00038 GetPKeyEC((obj), pkey); \
00039 (key) = pkey->pkey.ec; \
00040 } while(0)
00041
00042 #define Require_EC_KEY(obj, key) do { \
00043 Get_EC_KEY((obj), (key)); \
00044 if ((key) == NULL) \
00045 ossl_raise(eECError, "EC_KEY is not initialized"); \
00046 } while(0)
00047
00048 #define SafeRequire_EC_KEY(obj, key) do { \
00049 OSSL_Check_Kind((obj), cEC); \
00050 Require_EC_KEY((obj), (key)); \
00051 } while (0)
00052
00053 #define Get_EC_GROUP(obj, g) do { \
00054 ossl_ec_group *ec_group; \
00055 Data_Get_Struct((obj), ossl_ec_group, ec_group); \
00056 if (ec_group == NULL) \
00057 ossl_raise(eEC_GROUP, "missing ossl_ec_group structure"); \
00058 (g) = ec_group->group; \
00059 } while(0)
00060
00061 #define Require_EC_GROUP(obj, group) do { \
00062 Get_EC_GROUP((obj), (group)); \
00063 if ((group) == NULL) \
00064 ossl_raise(eEC_GROUP, "EC_GROUP is not initialized"); \
00065 } while(0)
00066
00067 #define SafeRequire_EC_GROUP(obj, group) do { \
00068 OSSL_Check_Kind((obj), cEC_GROUP); \
00069 Require_EC_GROUP((obj), (group)); \
00070 } while(0)
00071
00072 #define Get_EC_POINT(obj, p) do { \
00073 ossl_ec_point *ec_point; \
00074 Data_Get_Struct((obj), ossl_ec_point, ec_point); \
00075 if (ec_point == NULL) \
00076 ossl_raise(eEC_POINT, "missing ossl_ec_point structure"); \
00077 (p) = ec_point->point; \
00078 } while(0)
00079
00080 #define Require_EC_POINT(obj, point) do { \
00081 Get_EC_POINT((obj), (point)); \
00082 if ((point) == NULL) \
00083 ossl_raise(eEC_POINT, "EC_POINT is not initialized"); \
00084 } while(0)
00085
00086 #define SafeRequire_EC_POINT(obj, point) do { \
00087 OSSL_Check_Kind((obj), cEC_POINT); \
00088 Require_EC_POINT((obj), (point)); \
00089 } while(0)
00090
00091 VALUE cEC;
00092 VALUE eECError;
00093 VALUE cEC_GROUP;
00094 VALUE eEC_GROUP;
00095 VALUE cEC_POINT;
00096 VALUE eEC_POINT;
00097
00098 static ID s_GFp;
00099 static ID s_GFp_simple;
00100 static ID s_GFp_mont;
00101 static ID s_GFp_nist;
00102 static ID s_GF2m;
00103 static ID s_GF2m_simple;
00104
00105 static ID ID_uncompressed;
00106 static ID ID_compressed;
00107 static ID ID_hybrid;
00108
00109 static VALUE ec_instance(VALUE klass, EC_KEY *ec)
00110 {
00111 EVP_PKEY *pkey;
00112 VALUE obj;
00113
00114 if (!ec) {
00115 return Qfalse;
00116 }
00117 if (!(pkey = EVP_PKEY_new())) {
00118 return Qfalse;
00119 }
00120 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
00121 EVP_PKEY_free(pkey);
00122 return Qfalse;
00123 }
00124 WrapPKey(klass, obj, pkey);
00125
00126 return obj;
00127 }
00128
00129 VALUE ossl_ec_new(EVP_PKEY *pkey)
00130 {
00131 VALUE obj;
00132
00133 if (!pkey) {
00134 obj = ec_instance(cEC, EC_KEY_new());
00135 } else {
00136 if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
00137 ossl_raise(rb_eTypeError, "Not a EC key!");
00138 }
00139 WrapPKey(cEC, obj, pkey);
00140 }
00141 if (obj == Qfalse) {
00142 ossl_raise(eECError, NULL);
00143 }
00144
00145 return obj;
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161 static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
00162 {
00163 EVP_PKEY *pkey;
00164 EC_KEY *ec = NULL;
00165 VALUE arg, pass;
00166 VALUE group = Qnil;
00167 char *passwd = NULL;
00168
00169 GetPKey(self, pkey);
00170 if (pkey->pkey.ec)
00171 ossl_raise(eECError, "EC_KEY already initialized");
00172
00173 rb_scan_args(argc, argv, "02", &arg, &pass);
00174
00175 if (NIL_P(arg)) {
00176 ec = EC_KEY_new();
00177 } else {
00178 if (rb_obj_is_kind_of(arg, cEC)) {
00179 EC_KEY *other_ec = NULL;
00180
00181 SafeRequire_EC_KEY(arg, other_ec);
00182 ec = EC_KEY_dup(other_ec);
00183 } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
00184 ec = EC_KEY_new();
00185 group = arg;
00186 } else {
00187 BIO *in = ossl_obj2bio(arg);
00188
00189 if (!NIL_P(pass)) {
00190 passwd = StringValuePtr(pass);
00191 }
00192 ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, passwd);
00193 if (!ec) {
00194 OSSL_BIO_reset(in);
00195 ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, passwd);
00196 }
00197 if (!ec) {
00198 OSSL_BIO_reset(in);
00199 ec = d2i_ECPrivateKey_bio(in, NULL);
00200 }
00201 if (!ec) {
00202 OSSL_BIO_reset(in);
00203 ec = d2i_EC_PUBKEY_bio(in, NULL);
00204 }
00205
00206 BIO_free(in);
00207
00208 if (ec == NULL) {
00209 const char *name = StringValueCStr(arg);
00210 int nid = OBJ_sn2nid(name);
00211
00212 (void)ERR_get_error();
00213 if (nid == NID_undef)
00214 ossl_raise(eECError, "unknown curve name (%s)\n", name);
00215
00216 if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
00217 ossl_raise(eECError, "unable to create curve (%s)\n", name);
00218
00219 EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
00220 EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
00221 }
00222 }
00223 }
00224
00225 if (ec == NULL)
00226 ossl_raise(eECError, NULL);
00227
00228 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
00229 EC_KEY_free(ec);
00230 ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
00231 }
00232
00233 rb_iv_set(self, "@group", Qnil);
00234
00235 if (!NIL_P(group))
00236 rb_funcall(self, rb_intern("group="), 1, arg);
00237
00238 return self;
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248 static VALUE ossl_ec_key_get_group(VALUE self)
00249 {
00250 VALUE group_v;
00251 EC_KEY *ec;
00252 ossl_ec_group *ec_group;
00253 EC_GROUP *group;
00254
00255 Require_EC_KEY(self, ec);
00256
00257 group_v = rb_iv_get(self, "@group");
00258 if (!NIL_P(group_v))
00259 return group_v;
00260
00261 if ((group = (EC_GROUP *)EC_KEY_get0_group(ec)) != NULL) {
00262 group_v = rb_obj_alloc(cEC_GROUP);
00263 SafeGet_ec_group(group_v, ec_group);
00264 ec_group->group = group;
00265 ec_group->dont_free = 1;
00266 rb_iv_set(group_v, "@key", self);
00267 rb_iv_set(self, "@group", group_v);
00268 return group_v;
00269 }
00270
00271 return Qnil;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290 static VALUE ossl_ec_key_set_group(VALUE self, VALUE group_v)
00291 {
00292 VALUE old_group_v;
00293 EC_KEY *ec;
00294 EC_GROUP *group;
00295
00296 Require_EC_KEY(self, ec);
00297 SafeRequire_EC_GROUP(group_v, group);
00298
00299 old_group_v = rb_iv_get(self, "@group");
00300 if (!NIL_P(old_group_v)) {
00301 ossl_ec_group *old_ec_group;
00302 SafeGet_ec_group(old_group_v, old_ec_group);
00303
00304 old_ec_group->group = NULL;
00305 old_ec_group->dont_free = 0;
00306 rb_iv_set(old_group_v, "@key", Qnil);
00307 }
00308
00309 rb_iv_set(self, "@group", Qnil);
00310
00311 if (EC_KEY_set_group(ec, group) != 1)
00312 ossl_raise(eECError, "EC_KEY_set_group");
00313
00314 return group_v;
00315 }
00316
00317
00318
00319
00320
00321
00322
00323 static VALUE ossl_ec_key_get_private_key(VALUE self)
00324 {
00325 EC_KEY *ec;
00326 const BIGNUM *bn;
00327
00328 Require_EC_KEY(self, ec);
00329
00330 if ((bn = EC_KEY_get0_private_key(ec)) == NULL)
00331 return Qnil;
00332
00333 return ossl_bn_new(bn);
00334 }
00335
00336
00337
00338
00339
00340
00341
00342 static VALUE ossl_ec_key_set_private_key(VALUE self, VALUE private_key)
00343 {
00344 EC_KEY *ec;
00345 BIGNUM *bn = NULL;
00346
00347 Require_EC_KEY(self, ec);
00348 if (!NIL_P(private_key))
00349 bn = GetBNPtr(private_key);
00350
00351 switch (EC_KEY_set_private_key(ec, bn)) {
00352 case 1:
00353 break;
00354 case 0:
00355 if (bn == NULL)
00356 break;
00357 default:
00358 ossl_raise(eECError, "EC_KEY_set_private_key");
00359 }
00360
00361 return private_key;
00362 }
00363
00364
00365 static VALUE ossl_ec_point_dup(const EC_POINT *point, VALUE group_v)
00366 {
00367 VALUE obj;
00368 const EC_GROUP *group;
00369 ossl_ec_point *new_point;
00370
00371 obj = rb_obj_alloc(cEC_POINT);
00372 Data_Get_Struct(obj, ossl_ec_point, new_point);
00373
00374 SafeRequire_EC_GROUP(group_v, group);
00375
00376 new_point->point = EC_POINT_dup(point, group);
00377 if (new_point->point == NULL)
00378 ossl_raise(eEC_POINT, "EC_POINT_dup");
00379 rb_iv_set(obj, "@group", group_v);
00380
00381 return obj;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 static VALUE ossl_ec_key_get_public_key(VALUE self)
00391 {
00392 EC_KEY *ec;
00393 const EC_POINT *point;
00394 VALUE group;
00395
00396 Require_EC_KEY(self, ec);
00397
00398 if ((point = EC_KEY_get0_public_key(ec)) == NULL)
00399 return Qnil;
00400
00401 group = rb_funcall(self, rb_intern("group"), 0);
00402 if (NIL_P(group))
00403 ossl_raise(eECError, "EC_KEY_get0_get0_group (has public_key but no group???");
00404
00405 return ossl_ec_point_dup(point, group);
00406 }
00407
00408
00409
00410
00411
00412
00413
00414 static VALUE ossl_ec_key_set_public_key(VALUE self, VALUE public_key)
00415 {
00416 EC_KEY *ec;
00417 EC_POINT *point = NULL;
00418
00419 Require_EC_KEY(self, ec);
00420 if (!NIL_P(public_key))
00421 SafeRequire_EC_POINT(public_key, point);
00422
00423 switch (EC_KEY_set_public_key(ec, point)) {
00424 case 1:
00425 break;
00426 case 0:
00427 if (point == NULL)
00428 break;
00429 default:
00430 ossl_raise(eECError, "EC_KEY_set_public_key");
00431 }
00432
00433 return public_key;
00434 }
00435
00436
00437
00438
00439
00440
00441
00442 static VALUE ossl_ec_key_is_public_key(VALUE self)
00443 {
00444 EC_KEY *ec;
00445
00446 Require_EC_KEY(self, ec);
00447
00448 return (EC_KEY_get0_public_key(ec) ? Qtrue : Qfalse);
00449 }
00450
00451
00452
00453
00454
00455
00456
00457 static VALUE ossl_ec_key_is_private_key(VALUE self)
00458 {
00459 EC_KEY *ec;
00460
00461 Require_EC_KEY(self, ec);
00462
00463 return (EC_KEY_get0_private_key(ec) ? Qtrue : Qfalse);
00464 }
00465
00466 static VALUE ossl_ec_key_to_string(VALUE self, VALUE ciph, VALUE pass, int format)
00467 {
00468 EC_KEY *ec;
00469 BIO *out;
00470 int i = -1;
00471 int private = 0;
00472 char *password = NULL;
00473 VALUE str;
00474
00475 Require_EC_KEY(self, ec);
00476
00477 if (EC_KEY_get0_public_key(ec) == NULL)
00478 ossl_raise(eECError, "can't export - no public key set");
00479
00480 if (EC_KEY_check_key(ec) != 1)
00481 ossl_raise(eECError, "can't export - EC_KEY_check_key failed");
00482
00483 if (EC_KEY_get0_private_key(ec))
00484 private = 1;
00485
00486 if (!(out = BIO_new(BIO_s_mem())))
00487 ossl_raise(eECError, "BIO_new(BIO_s_mem())");
00488
00489 switch(format) {
00490 case EXPORT_PEM:
00491 if (private) {
00492 const EVP_CIPHER *cipher;
00493 if (!NIL_P(ciph)) {
00494 cipher = GetCipherPtr(ciph);
00495 if (!NIL_P(pass)) {
00496 StringValue(pass);
00497 if (RSTRING_LENINT(pass) < OSSL_MIN_PWD_LEN)
00498 ossl_raise(eOSSLError, "OpenSSL requires passwords to be at least four characters long");
00499 password = RSTRING_PTR(pass);
00500 }
00501 }
00502 else {
00503 cipher = NULL;
00504 }
00505 i = PEM_write_bio_ECPrivateKey(out, ec, cipher, NULL, 0, NULL, password);
00506 } else {
00507 i = PEM_write_bio_EC_PUBKEY(out, ec);
00508 }
00509
00510 break;
00511 case EXPORT_DER:
00512 if (private) {
00513 i = i2d_ECPrivateKey_bio(out, ec);
00514 } else {
00515 i = i2d_EC_PUBKEY_bio(out, ec);
00516 }
00517
00518 break;
00519 default:
00520 BIO_free(out);
00521 ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
00522 }
00523
00524 if (i != 1) {
00525 BIO_free(out);
00526 ossl_raise(eECError, "outlen=%d", i);
00527 }
00528
00529 str = ossl_membio2str(out);
00530
00531 return str;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 static VALUE ossl_ec_key_export(int argc, VALUE *argv, VALUE self)
00547 {
00548 VALUE cipher, passwd;
00549 rb_scan_args(argc, argv, "02", &cipher, &passwd);
00550 return ossl_ec_key_to_string(self, cipher, passwd, EXPORT_PEM);
00551 }
00552
00553
00554
00555
00556
00557
00558
00559 static VALUE ossl_ec_key_to_der(VALUE self)
00560 {
00561 return ossl_ec_key_to_string(self, Qnil, Qnil, EXPORT_DER);
00562 }
00563
00564
00565
00566
00567
00568
00569
00570 static VALUE ossl_ec_key_to_text(VALUE self)
00571 {
00572 EC_KEY *ec;
00573 BIO *out;
00574 VALUE str;
00575
00576 Require_EC_KEY(self, ec);
00577 if (!(out = BIO_new(BIO_s_mem()))) {
00578 ossl_raise(eECError, "BIO_new(BIO_s_mem())");
00579 }
00580 if (!EC_KEY_print(out, ec, 0)) {
00581 BIO_free(out);
00582 ossl_raise(eECError, "EC_KEY_print");
00583 }
00584 str = ossl_membio2str(out);
00585
00586 return str;
00587 }
00588
00589
00590
00591
00592
00593
00594
00595 static VALUE ossl_ec_key_generate_key(VALUE self)
00596 {
00597 EC_KEY *ec;
00598
00599 Require_EC_KEY(self, ec);
00600
00601 if (EC_KEY_generate_key(ec) != 1)
00602 ossl_raise(eECError, "EC_KEY_generate_key");
00603
00604 return self;
00605 }
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615 static VALUE ossl_ec_key_check_key(VALUE self)
00616 {
00617 EC_KEY *ec;
00618
00619 Require_EC_KEY(self, ec);
00620
00621 if (EC_KEY_check_key(ec) != 1)
00622 ossl_raise(eECError, "EC_KEY_check_key");
00623
00624 return Qtrue;
00625 }
00626
00627
00628
00629
00630
00631
00632
00633 static VALUE ossl_ec_key_dh_compute_key(VALUE self, VALUE pubkey)
00634 {
00635 EC_KEY *ec;
00636 EC_POINT *point;
00637 int buf_len;
00638 VALUE str;
00639
00640 Require_EC_KEY(self, ec);
00641 SafeRequire_EC_POINT(pubkey, point);
00642
00643
00644 buf_len = 1024;
00645 str = rb_str_new(0, buf_len);
00646
00647 buf_len = ECDH_compute_key(RSTRING_PTR(str), buf_len, point, ec, NULL);
00648 if (buf_len < 0)
00649 ossl_raise(eECError, "ECDH_compute_key");
00650
00651 rb_str_resize(str, buf_len);
00652
00653 return str;
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 static VALUE ossl_ec_key_dsa_sign_asn1(VALUE self, VALUE data)
00665 {
00666 EC_KEY *ec;
00667 unsigned int buf_len;
00668 VALUE str;
00669
00670 Require_EC_KEY(self, ec);
00671 StringValue(data);
00672
00673 if (EC_KEY_get0_private_key(ec) == NULL)
00674 ossl_raise(eECError, "Private EC key needed!");
00675
00676 str = rb_str_new(0, ECDSA_size(ec) + 16);
00677 if (ECDSA_sign(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(str), &buf_len, ec) != 1)
00678 ossl_raise(eECError, "ECDSA_sign");
00679
00680 rb_str_resize(str, buf_len);
00681
00682 return str;
00683 }
00684
00685
00686
00687
00688
00689
00690
00691 static VALUE ossl_ec_key_dsa_verify_asn1(VALUE self, VALUE data, VALUE sig)
00692 {
00693 EC_KEY *ec;
00694
00695 Require_EC_KEY(self, ec);
00696 StringValue(data);
00697 StringValue(sig);
00698
00699 switch (ECDSA_verify(0, (unsigned char *) RSTRING_PTR(data), RSTRING_LENINT(data), (unsigned char *) RSTRING_PTR(sig), (int)RSTRING_LEN(sig), ec)) {
00700 case 1: return Qtrue;
00701 case 0: return Qfalse;
00702 default: break;
00703 }
00704
00705 ossl_raise(eECError, "ECDSA_verify");
00706
00707 UNREACHABLE;
00708 }
00709
00710 static void ossl_ec_group_free(ossl_ec_group *ec_group)
00711 {
00712 if (!ec_group->dont_free && ec_group->group)
00713 EC_GROUP_clear_free(ec_group->group);
00714 ruby_xfree(ec_group);
00715 }
00716
00717 static VALUE ossl_ec_group_alloc(VALUE klass)
00718 {
00719 ossl_ec_group *ec_group;
00720 VALUE obj;
00721
00722 obj = Data_Make_Struct(klass, ossl_ec_group, 0, ossl_ec_group_free, ec_group);
00723
00724 return obj;
00725 }
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
00744 {
00745 VALUE arg1, arg2, arg3, arg4;
00746 ossl_ec_group *ec_group;
00747 EC_GROUP *group = NULL;
00748
00749 Data_Get_Struct(self, ossl_ec_group, ec_group);
00750 if (ec_group->group != NULL)
00751 ossl_raise(rb_eRuntimeError, "EC_GROUP is already initialized");
00752
00753 switch (rb_scan_args(argc, argv, "13", &arg1, &arg2, &arg3, &arg4)) {
00754 case 1:
00755 if (SYMBOL_P(arg1)) {
00756 const EC_METHOD *method = NULL;
00757 ID id = SYM2ID(arg1);
00758
00759 if (id == s_GFp_simple) {
00760 method = EC_GFp_simple_method();
00761 } else if (id == s_GFp_mont) {
00762 method = EC_GFp_mont_method();
00763 } else if (id == s_GFp_nist) {
00764 method = EC_GFp_nist_method();
00765 #if !defined(OPENSSL_NO_EC2M)
00766 } else if (id == s_GF2m_simple) {
00767 method = EC_GF2m_simple_method();
00768 #endif
00769 }
00770
00771 if (method) {
00772 if ((group = EC_GROUP_new(method)) == NULL)
00773 ossl_raise(eEC_GROUP, "EC_GROUP_new");
00774 } else {
00775 ossl_raise(rb_eArgError, "unknown symbol, must be :GFp_simple, :GFp_mont, :GFp_nist or :GF2m_simple");
00776 }
00777 } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
00778 const EC_GROUP *arg1_group;
00779
00780 SafeRequire_EC_GROUP(arg1, arg1_group);
00781 if ((group = EC_GROUP_dup(arg1_group)) == NULL)
00782 ossl_raise(eEC_GROUP, "EC_GROUP_dup");
00783 } else {
00784 BIO *in = ossl_obj2bio(arg1);
00785
00786 group = PEM_read_bio_ECPKParameters(in, NULL, NULL, NULL);
00787 if (!group) {
00788 OSSL_BIO_reset(in);
00789 group = d2i_ECPKParameters_bio(in, NULL);
00790 }
00791
00792 BIO_free(in);
00793
00794 if (!group) {
00795 const char *name = StringValueCStr(arg1);
00796 int nid = OBJ_sn2nid(name);
00797
00798 (void)ERR_get_error();
00799 if (nid == NID_undef)
00800 ossl_raise(eEC_GROUP, "unknown curve name (%s)", name);
00801
00802 group = EC_GROUP_new_by_curve_name(nid);
00803 if (group == NULL)
00804 ossl_raise(eEC_GROUP, "unable to create curve (%s)", name);
00805
00806 EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
00807 EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
00808 }
00809 }
00810
00811 break;
00812 case 4:
00813 if (SYMBOL_P(arg1)) {
00814 ID id = SYM2ID(arg1);
00815 EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL;
00816 const BIGNUM *p = GetBNPtr(arg2);
00817 const BIGNUM *a = GetBNPtr(arg3);
00818 const BIGNUM *b = GetBNPtr(arg4);
00819
00820 if (id == s_GFp) {
00821 new_curve = EC_GROUP_new_curve_GFp;
00822 #if !defined(OPENSSL_NO_EC2M)
00823 } else if (id == s_GF2m) {
00824 new_curve = EC_GROUP_new_curve_GF2m;
00825 #endif
00826 } else {
00827 ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m");
00828 }
00829
00830 if ((group = new_curve(p, a, b, ossl_bn_ctx)) == NULL)
00831 ossl_raise(eEC_GROUP, "EC_GROUP_new_by_GF*");
00832 } else {
00833 ossl_raise(rb_eArgError, "unknown argument, must be :GFp or :GF2m");
00834 }
00835
00836 break;
00837 default:
00838 ossl_raise(rb_eArgError, "wrong number of arguments");
00839 }
00840
00841 if (group == NULL)
00842 ossl_raise(eEC_GROUP, "");
00843
00844 ec_group->group = group;
00845
00846 return self;
00847 }
00848
00849
00850
00851
00852
00853 static VALUE ossl_ec_group_eql(VALUE a, VALUE b)
00854 {
00855 EC_GROUP *group1 = NULL, *group2 = NULL;
00856
00857 Require_EC_GROUP(a, group1);
00858 SafeRequire_EC_GROUP(b, group2);
00859
00860 if (EC_GROUP_cmp(group1, group2, ossl_bn_ctx) == 1)
00861 return Qfalse;
00862
00863 return Qtrue;
00864 }
00865
00866
00867
00868
00869
00870
00871 static VALUE ossl_ec_group_get_generator(VALUE self)
00872 {
00873 VALUE point_obj;
00874 EC_GROUP *group = NULL;
00875
00876 Require_EC_GROUP(self, group);
00877
00878 point_obj = ossl_ec_point_dup(EC_GROUP_get0_generator(group), self);
00879
00880 return point_obj;
00881 }
00882
00883
00884
00885
00886
00887
00888 static VALUE ossl_ec_group_set_generator(VALUE self, VALUE generator, VALUE order, VALUE cofactor)
00889 {
00890 EC_GROUP *group = NULL;
00891 const EC_POINT *point;
00892 const BIGNUM *o, *co;
00893
00894 Require_EC_GROUP(self, group);
00895 SafeRequire_EC_POINT(generator, point);
00896 o = GetBNPtr(order);
00897 co = GetBNPtr(cofactor);
00898
00899 if (EC_GROUP_set_generator(group, point, o, co) != 1)
00900 ossl_raise(eEC_GROUP, "EC_GROUP_set_generator");
00901
00902 return self;
00903 }
00904
00905
00906
00907
00908
00909
00910 static VALUE ossl_ec_group_get_order(VALUE self)
00911 {
00912 VALUE bn_obj;
00913 BIGNUM *bn;
00914 EC_GROUP *group = NULL;
00915
00916 Require_EC_GROUP(self, group);
00917
00918 bn_obj = ossl_bn_new(NULL);
00919 bn = GetBNPtr(bn_obj);
00920
00921 if (EC_GROUP_get_order(group, bn, ossl_bn_ctx) != 1)
00922 ossl_raise(eEC_GROUP, "EC_GROUP_get_order");
00923
00924 return bn_obj;
00925 }
00926
00927
00928
00929
00930
00931
00932 static VALUE ossl_ec_group_get_cofactor(VALUE self)
00933 {
00934 VALUE bn_obj;
00935 BIGNUM *bn;
00936 EC_GROUP *group = NULL;
00937
00938 Require_EC_GROUP(self, group);
00939
00940 bn_obj = ossl_bn_new(NULL);
00941 bn = GetBNPtr(bn_obj);
00942
00943 if (EC_GROUP_get_cofactor(group, bn, ossl_bn_ctx) != 1)
00944 ossl_raise(eEC_GROUP, "EC_GROUP_get_cofactor");
00945
00946 return bn_obj;
00947 }
00948
00949
00950
00951
00952
00953
00954 static VALUE ossl_ec_group_get_curve_name(VALUE self)
00955 {
00956 EC_GROUP *group = NULL;
00957 int nid;
00958
00959 Get_EC_GROUP(self, group);
00960 if (group == NULL)
00961 return Qnil;
00962
00963 nid = EC_GROUP_get_curve_name(group);
00964
00965
00966 return rb_str_new2(OBJ_nid2sn(nid));
00967 }
00968
00969
00970
00971
00972
00973
00974 static VALUE ossl_s_builtin_curves(VALUE self)
00975 {
00976 EC_builtin_curve *curves = NULL;
00977 int n;
00978 int crv_len = rb_long2int(EC_get_builtin_curves(NULL, 0));
00979 VALUE ary, ret;
00980
00981 curves = ALLOCA_N(EC_builtin_curve, crv_len);
00982 if (curves == NULL)
00983 return Qnil;
00984 if (!EC_get_builtin_curves(curves, crv_len))
00985 ossl_raise(rb_eRuntimeError, "EC_get_builtin_curves");
00986
00987 ret = rb_ary_new2(crv_len);
00988
00989 for (n = 0; n < crv_len; n++) {
00990 const char *sname = OBJ_nid2sn(curves[n].nid);
00991 const char *comment = curves[n].comment;
00992
00993 ary = rb_ary_new2(2);
00994 rb_ary_push(ary, rb_str_new2(sname));
00995 rb_ary_push(ary, comment ? rb_str_new2(comment) : Qnil);
00996 rb_ary_push(ret, ary);
00997 }
00998
00999 return ret;
01000 }
01001
01002
01003
01004
01005
01006
01007 static VALUE ossl_ec_group_get_asn1_flag(VALUE self)
01008 {
01009 EC_GROUP *group = NULL;
01010 int flag;
01011
01012 Require_EC_GROUP(self, group);
01013
01014 flag = EC_GROUP_get_asn1_flag(group);
01015
01016 return INT2FIX(flag);
01017 }
01018
01019
01020
01021
01022
01023
01024 static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v)
01025 {
01026 EC_GROUP *group = NULL;
01027
01028 Require_EC_GROUP(self, group);
01029
01030 EC_GROUP_set_asn1_flag(group, NUM2INT(flag_v));
01031
01032 return flag_v;
01033 }
01034
01035
01036
01037
01038
01039
01040 static VALUE ossl_ec_group_get_point_conversion_form(VALUE self)
01041 {
01042 EC_GROUP *group = NULL;
01043 point_conversion_form_t form;
01044 VALUE ret;
01045
01046 Require_EC_GROUP(self, group);
01047
01048 form = EC_GROUP_get_point_conversion_form(group);
01049
01050 switch (form) {
01051 case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break;
01052 case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break;
01053 case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break;
01054 default: ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form);
01055 }
01056
01057 return ID2SYM(ret);
01058 }
01059
01060
01061
01062
01063
01064
01065 static VALUE ossl_ec_group_set_point_conversion_form(VALUE self, VALUE form_v)
01066 {
01067 EC_GROUP *group = NULL;
01068 point_conversion_form_t form;
01069 ID form_id = SYM2ID(form_v);
01070
01071 Require_EC_GROUP(self, group);
01072
01073 if (form_id == ID_uncompressed) {
01074 form = POINT_CONVERSION_UNCOMPRESSED;
01075 } else if (form_id == ID_compressed) {
01076 form = POINT_CONVERSION_COMPRESSED;
01077 } else if (form_id == ID_hybrid) {
01078 form = POINT_CONVERSION_HYBRID;
01079 } else {
01080 ossl_raise(rb_eArgError, "form must be :compressed, :uncompressed, or :hybrid");
01081 }
01082
01083 EC_GROUP_set_point_conversion_form(group, form);
01084
01085 return form_v;
01086 }
01087
01088
01089
01090
01091
01092
01093 static VALUE ossl_ec_group_get_seed(VALUE self)
01094 {
01095 EC_GROUP *group = NULL;
01096 size_t seed_len;
01097
01098 Require_EC_GROUP(self, group);
01099
01100 seed_len = EC_GROUP_get_seed_len(group);
01101
01102 if (seed_len == 0)
01103 return Qnil;
01104
01105 return rb_str_new((const char *)EC_GROUP_get0_seed(group), seed_len);
01106 }
01107
01108
01109
01110
01111
01112
01113 static VALUE ossl_ec_group_set_seed(VALUE self, VALUE seed)
01114 {
01115 EC_GROUP *group = NULL;
01116
01117 Require_EC_GROUP(self, group);
01118 StringValue(seed);
01119
01120 if (EC_GROUP_set_seed(group, (unsigned char *)RSTRING_PTR(seed), RSTRING_LEN(seed)) != (size_t)RSTRING_LEN(seed))
01121 ossl_raise(eEC_GROUP, "EC_GROUP_set_seed");
01122
01123 return seed;
01124 }
01125
01126
01127
01128
01129
01130
01131
01132
01133 static VALUE ossl_ec_group_get_degree(VALUE self)
01134 {
01135 EC_GROUP *group = NULL;
01136
01137 Require_EC_GROUP(self, group);
01138
01139 return INT2NUM(EC_GROUP_get_degree(group));
01140 }
01141
01142 static VALUE ossl_ec_group_to_string(VALUE self, int format)
01143 {
01144 EC_GROUP *group;
01145 BIO *out;
01146 int i = -1;
01147 VALUE str;
01148
01149 Get_EC_GROUP(self, group);
01150
01151 if (!(out = BIO_new(BIO_s_mem())))
01152 ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
01153
01154 switch(format) {
01155 case EXPORT_PEM:
01156 i = PEM_write_bio_ECPKParameters(out, group);
01157 break;
01158 case EXPORT_DER:
01159 i = i2d_ECPKParameters_bio(out, group);
01160 break;
01161 default:
01162 BIO_free(out);
01163 ossl_raise(rb_eRuntimeError, "unknown format (internal error)");
01164 }
01165
01166 if (i != 1) {
01167 BIO_free(out);
01168 ossl_raise(eECError, NULL);
01169 }
01170
01171 str = ossl_membio2str(out);
01172
01173 return str;
01174 }
01175
01176
01177
01178
01179
01180
01181 static VALUE ossl_ec_group_to_pem(VALUE self)
01182 {
01183 return ossl_ec_group_to_string(self, EXPORT_PEM);
01184 }
01185
01186
01187
01188
01189
01190
01191 static VALUE ossl_ec_group_to_der(VALUE self)
01192 {
01193 return ossl_ec_group_to_string(self, EXPORT_DER);
01194 }
01195
01196
01197
01198
01199
01200
01201 static VALUE ossl_ec_group_to_text(VALUE self)
01202 {
01203 EC_GROUP *group;
01204 BIO *out;
01205 VALUE str;
01206
01207 Require_EC_GROUP(self, group);
01208 if (!(out = BIO_new(BIO_s_mem()))) {
01209 ossl_raise(eEC_GROUP, "BIO_new(BIO_s_mem())");
01210 }
01211 if (!ECPKParameters_print(out, group, 0)) {
01212 BIO_free(out);
01213 ossl_raise(eEC_GROUP, NULL);
01214 }
01215 str = ossl_membio2str(out);
01216
01217 return str;
01218 }
01219
01220
01221 static void ossl_ec_point_free(ossl_ec_point *ec_point)
01222 {
01223 if (!ec_point->dont_free && ec_point->point)
01224 EC_POINT_clear_free(ec_point->point);
01225 ruby_xfree(ec_point);
01226 }
01227
01228 static VALUE ossl_ec_point_alloc(VALUE klass)
01229 {
01230 ossl_ec_point *ec_point;
01231 VALUE obj;
01232
01233 obj = Data_Make_Struct(klass, ossl_ec_point, 0, ossl_ec_point_free, ec_point);
01234
01235 return obj;
01236 }
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246 static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
01247 {
01248 ossl_ec_point *ec_point;
01249 EC_POINT *point = NULL;
01250 VALUE arg1, arg2;
01251 VALUE group_v = Qnil;
01252 const EC_GROUP *group = NULL;
01253
01254 Data_Get_Struct(self, ossl_ec_point, ec_point);
01255 if (ec_point->point)
01256 ossl_raise(eEC_POINT, "EC_POINT already initialized");
01257
01258 switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) {
01259 case 1:
01260 if (rb_obj_is_kind_of(arg1, cEC_POINT)) {
01261 const EC_POINT *arg_point;
01262
01263 group_v = rb_iv_get(arg1, "@group");
01264 SafeRequire_EC_GROUP(group_v, group);
01265 SafeRequire_EC_POINT(arg1, arg_point);
01266
01267 point = EC_POINT_dup(arg_point, group);
01268 } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) {
01269 group_v = arg1;
01270 SafeRequire_EC_GROUP(group_v, group);
01271
01272 point = EC_POINT_new(group);
01273 } else {
01274 ossl_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group");
01275 }
01276
01277 break;
01278 case 2:
01279 if (!rb_obj_is_kind_of(arg1, cEC_GROUP))
01280 ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group");
01281 group_v = arg1;
01282 SafeRequire_EC_GROUP(group_v, group);
01283
01284 if (rb_obj_is_kind_of(arg2, cBN)) {
01285 const BIGNUM *bn = GetBNPtr(arg2);
01286
01287 point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx);
01288 } else {
01289 BIO *in = ossl_obj2bio(arg1);
01290
01291
01292
01293 BIO_free(in);
01294
01295 if (point == NULL) {
01296 ossl_raise(eEC_POINT, "unknown type for 2nd arg");
01297 }
01298 }
01299 break;
01300 default:
01301 ossl_raise(rb_eArgError, "wrong number of arguments");
01302 }
01303
01304 if (point == NULL)
01305 ossl_raise(eEC_POINT, NULL);
01306
01307 if (NIL_P(group_v))
01308 ossl_raise(rb_eRuntimeError, "missing group (internal error)");
01309
01310 ec_point->point = point;
01311
01312 rb_iv_set(self, "@group", group_v);
01313
01314 return self;
01315 }
01316
01317
01318
01319
01320
01321
01322 static VALUE ossl_ec_point_eql(VALUE a, VALUE b)
01323 {
01324 EC_POINT *point1, *point2;
01325 VALUE group_v1 = rb_iv_get(a, "@group");
01326 VALUE group_v2 = rb_iv_get(b, "@group");
01327 const EC_GROUP *group;
01328
01329 if (ossl_ec_group_eql(group_v1, group_v2) == Qfalse)
01330 return Qfalse;
01331
01332 Require_EC_POINT(a, point1);
01333 SafeRequire_EC_POINT(b, point2);
01334 SafeRequire_EC_GROUP(group_v1, group);
01335
01336 if (EC_POINT_cmp(group, point1, point2, ossl_bn_ctx) == 1)
01337 return Qfalse;
01338
01339 return Qtrue;
01340 }
01341
01342
01343
01344
01345
01346
01347 static VALUE ossl_ec_point_is_at_infinity(VALUE self)
01348 {
01349 EC_POINT *point;
01350 VALUE group_v = rb_iv_get(self, "@group");
01351 const EC_GROUP *group;
01352
01353 Require_EC_POINT(self, point);
01354 SafeRequire_EC_GROUP(group_v, group);
01355
01356 switch (EC_POINT_is_at_infinity(group, point)) {
01357 case 1: return Qtrue;
01358 case 0: return Qfalse;
01359 default: ossl_raise(cEC_POINT, "EC_POINT_is_at_infinity");
01360 }
01361
01362 UNREACHABLE;
01363 }
01364
01365
01366
01367
01368
01369
01370 static VALUE ossl_ec_point_is_on_curve(VALUE self)
01371 {
01372 EC_POINT *point;
01373 VALUE group_v = rb_iv_get(self, "@group");
01374 const EC_GROUP *group;
01375
01376 Require_EC_POINT(self, point);
01377 SafeRequire_EC_GROUP(group_v, group);
01378
01379 switch (EC_POINT_is_on_curve(group, point, ossl_bn_ctx)) {
01380 case 1: return Qtrue;
01381 case 0: return Qfalse;
01382 default: ossl_raise(cEC_POINT, "EC_POINT_is_on_curve");
01383 }
01384
01385 UNREACHABLE;
01386 }
01387
01388
01389
01390
01391
01392
01393 static VALUE ossl_ec_point_make_affine(VALUE self)
01394 {
01395 EC_POINT *point;
01396 VALUE group_v = rb_iv_get(self, "@group");
01397 const EC_GROUP *group;
01398
01399 Require_EC_POINT(self, point);
01400 SafeRequire_EC_GROUP(group_v, group);
01401
01402 if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1)
01403 ossl_raise(cEC_POINT, "EC_POINT_make_affine");
01404
01405 return self;
01406 }
01407
01408
01409
01410
01411
01412
01413 static VALUE ossl_ec_point_invert(VALUE self)
01414 {
01415 EC_POINT *point;
01416 VALUE group_v = rb_iv_get(self, "@group");
01417 const EC_GROUP *group;
01418
01419 Require_EC_POINT(self, point);
01420 SafeRequire_EC_GROUP(group_v, group);
01421
01422 if (EC_POINT_invert(group, point, ossl_bn_ctx) != 1)
01423 ossl_raise(cEC_POINT, "EC_POINT_invert");
01424
01425 return self;
01426 }
01427
01428
01429
01430
01431
01432
01433 static VALUE ossl_ec_point_set_to_infinity(VALUE self)
01434 {
01435 EC_POINT *point;
01436 VALUE group_v = rb_iv_get(self, "@group");
01437 const EC_GROUP *group;
01438
01439 Require_EC_POINT(self, point);
01440 SafeRequire_EC_GROUP(group_v, group);
01441
01442 if (EC_POINT_set_to_infinity(group, point) != 1)
01443 ossl_raise(cEC_POINT, "EC_POINT_set_to_infinity");
01444
01445 return self;
01446 }
01447
01448
01449
01450
01451
01452
01453
01454 static VALUE ossl_ec_point_to_bn(VALUE self)
01455 {
01456 EC_POINT *point;
01457 VALUE bn_obj;
01458 VALUE group_v = rb_iv_get(self, "@group");
01459 const EC_GROUP *group;
01460 point_conversion_form_t form;
01461 BIGNUM *bn;
01462
01463 Require_EC_POINT(self, point);
01464 SafeRequire_EC_GROUP(group_v, group);
01465
01466 form = EC_GROUP_get_point_conversion_form(group);
01467
01468 bn_obj = rb_obj_alloc(cBN);
01469 bn = GetBNPtr(bn_obj);
01470
01471 if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL)
01472 ossl_raise(eEC_POINT, "EC_POINT_point2bn");
01473
01474 return bn_obj;
01475 }
01476
01477
01478
01479
01480
01481
01482
01483
01484 static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
01485 {
01486 EC_POINT *point1, *point2;
01487 const EC_GROUP *group;
01488 VALUE group_v = rb_iv_get(self, "@group");
01489 VALUE bn_v1, bn_v2, r, points_v;
01490 BIGNUM *bn1 = NULL, *bn2 = NULL;
01491
01492 Require_EC_POINT(self, point1);
01493 SafeRequire_EC_GROUP(group_v, group);
01494
01495 r = rb_obj_alloc(cEC_POINT);
01496 ossl_ec_point_initialize(1, &group_v, r);
01497 Require_EC_POINT(r, point2);
01498
01499 argc = rb_scan_args(argc, argv, "12", &bn_v1, &points_v, &bn_v2);
01500
01501 if (rb_obj_is_kind_of(bn_v1, cBN)) {
01502 bn1 = GetBNPtr(bn_v1);
01503 if (argc >= 2) {
01504 bn2 = GetBNPtr(points_v);
01505 }
01506 if (EC_POINT_mul(group, point2, bn2, point1, bn1, ossl_bn_ctx) != 1)
01507 ossl_raise(eEC_POINT, "Multiplication failed");
01508 } else {
01509 size_t i, points_len, bignums_len;
01510 const EC_POINT **points;
01511 const BIGNUM **bignums;
01512
01513 Check_Type(bn_v1, T_ARRAY);
01514 bignums_len = RARRAY_LEN(bn_v1);
01515 bignums = (const BIGNUM **)OPENSSL_malloc(bignums_len * (int)sizeof(BIGNUM *));
01516
01517 for (i = 0; i < bignums_len; ++i) {
01518 bignums[i] = GetBNPtr(rb_ary_entry(bn_v1, i));
01519 }
01520
01521 if (!rb_obj_is_kind_of(points_v, rb_cArray)) {
01522 OPENSSL_free((void *)bignums);
01523 rb_raise(rb_eTypeError, "Argument2 must be an array");
01524 }
01525
01526 rb_ary_unshift(points_v, self);
01527 points_len = RARRAY_LEN(points_v);
01528 points = (const EC_POINT **)OPENSSL_malloc(points_len * (int)sizeof(EC_POINT *));
01529
01530 for (i = 0; i < points_len; ++i) {
01531 Get_EC_POINT(rb_ary_entry(points_v, i), points[i]);
01532 }
01533
01534 if (argc >= 3) {
01535 bn2 = GetBNPtr(bn_v2);
01536 }
01537 if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums, ossl_bn_ctx) != 1) {
01538 OPENSSL_free((void *)bignums);
01539 OPENSSL_free((void *)points);
01540 ossl_raise(eEC_POINT, "Multiplication failed");
01541 }
01542 OPENSSL_free((void *)bignums);
01543 OPENSSL_free((void *)points);
01544 }
01545
01546 return r;
01547 }
01548
01549 static void no_copy(VALUE klass)
01550 {
01551 rb_undef_method(klass, "copy");
01552 rb_undef_method(klass, "clone");
01553 rb_undef_method(klass, "dup");
01554 rb_undef_method(klass, "initialize_copy");
01555 }
01556
01557 void Init_ossl_ec()
01558 {
01559 #ifdef DONT_NEED_RDOC_WORKAROUND
01560 mOSSL = rb_define_module("OpenSSL");
01561 mPKey = rb_define_module_under(mOSSL, "PKey");
01562 #endif
01563
01564 eECError = rb_define_class_under(mPKey, "ECError", ePKeyError);
01565
01566 cEC = rb_define_class_under(mPKey, "EC", cPKey);
01567 cEC_GROUP = rb_define_class_under(cEC, "Group", rb_cObject);
01568 cEC_POINT = rb_define_class_under(cEC, "Point", rb_cObject);
01569 eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError);
01570 eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError);
01571
01572 s_GFp = rb_intern("GFp");
01573 s_GF2m = rb_intern("GF2m");
01574 s_GFp_simple = rb_intern("GFp_simple");
01575 s_GFp_mont = rb_intern("GFp_mont");
01576 s_GFp_nist = rb_intern("GFp_nist");
01577 s_GF2m_simple = rb_intern("GF2m_simple");
01578
01579 ID_uncompressed = rb_intern("uncompressed");
01580 ID_compressed = rb_intern("compressed");
01581 ID_hybrid = rb_intern("hybrid");
01582
01583 #ifdef OPENSSL_EC_NAMED_CURVE
01584 rb_define_const(cEC, "NAMED_CURVE", ULONG2NUM(OPENSSL_EC_NAMED_CURVE));
01585 #endif
01586
01587 rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
01588
01589 rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
01590
01591
01592 rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
01593 rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1);
01594 rb_define_method(cEC, "private_key", ossl_ec_key_get_private_key, 0);
01595 rb_define_method(cEC, "private_key=", ossl_ec_key_set_private_key, 1);
01596 rb_define_method(cEC, "public_key", ossl_ec_key_get_public_key, 0);
01597 rb_define_method(cEC, "public_key=", ossl_ec_key_set_public_key, 1);
01598 rb_define_method(cEC, "private_key?", ossl_ec_key_is_private_key, 0);
01599 rb_define_method(cEC, "public_key?", ossl_ec_key_is_public_key, 0);
01600
01601
01602
01603
01604
01605
01606
01607 rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0);
01608 rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
01609
01610 rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
01611 rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
01612 rb_define_method(cEC, "dsa_verify_asn1", ossl_ec_key_dsa_verify_asn1, 2);
01613
01614
01615 rb_define_method(cEC, "export", ossl_ec_key_export, -1);
01616 rb_define_alias(cEC, "to_pem", "export");
01617 rb_define_method(cEC, "to_der", ossl_ec_key_to_der, 0);
01618 rb_define_method(cEC, "to_text", ossl_ec_key_to_text, 0);
01619
01620
01621 rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
01622 rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
01623 rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
01624 rb_define_alias(cEC_GROUP, "==", "eql?");
01625
01626
01627 rb_define_method(cEC_GROUP, "generator", ossl_ec_group_get_generator, 0);
01628 rb_define_method(cEC_GROUP, "set_generator", ossl_ec_group_set_generator, 3);
01629 rb_define_method(cEC_GROUP, "order", ossl_ec_group_get_order, 0);
01630 rb_define_method(cEC_GROUP, "cofactor", ossl_ec_group_get_cofactor, 0);
01631
01632 rb_define_method(cEC_GROUP, "curve_name", ossl_ec_group_get_curve_name, 0);
01633
01634
01635 rb_define_method(cEC_GROUP, "asn1_flag", ossl_ec_group_get_asn1_flag, 0);
01636 rb_define_method(cEC_GROUP, "asn1_flag=", ossl_ec_group_set_asn1_flag, 1);
01637
01638 rb_define_method(cEC_GROUP, "point_conversion_form", ossl_ec_group_get_point_conversion_form, 0);
01639 rb_define_method(cEC_GROUP, "point_conversion_form=", ossl_ec_group_set_point_conversion_form, 1);
01640
01641 rb_define_method(cEC_GROUP, "seed", ossl_ec_group_get_seed, 0);
01642 rb_define_method(cEC_GROUP, "seed=", ossl_ec_group_set_seed, 1);
01643
01644
01645
01646 rb_define_method(cEC_GROUP, "degree", ossl_ec_group_get_degree, 0);
01647
01648
01649
01650
01651 rb_define_method(cEC_GROUP, "to_pem", ossl_ec_group_to_pem, 0);
01652 rb_define_method(cEC_GROUP, "to_der", ossl_ec_group_to_der, 0);
01653 rb_define_method(cEC_GROUP, "to_text", ossl_ec_group_to_text, 0);
01654
01655
01656 rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
01657 rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
01658 rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
01659 rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
01660 rb_define_alias(cEC_POINT, "==", "eql?");
01661
01662 rb_define_method(cEC_POINT, "infinity?", ossl_ec_point_is_at_infinity, 0);
01663 rb_define_method(cEC_POINT, "on_curve?", ossl_ec_point_is_on_curve, 0);
01664 rb_define_method(cEC_POINT, "make_affine!", ossl_ec_point_make_affine, 0);
01665 rb_define_method(cEC_POINT, "invert!", ossl_ec_point_invert, 0);
01666 rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0);
01667
01668
01669 rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
01670 rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
01671
01672 no_copy(cEC);
01673 no_copy(cEC_GROUP);
01674 no_copy(cEC_POINT);
01675 }
01676
01677 #else
01678 void Init_ossl_ec()
01679 {
01680 }
01681 #endif
01682