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

Generated on Thu Sep 8 2011 03:50:35 for Ruby by  doxygen 1.7.1