• Main Page
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

ext/openssl/ossl_pkey_ec.c

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

Generated on Wed Sep 8 2010 21:54:07 for Ruby by  doxygen 1.7.1