|
Ruby 1.9.2p180(2011-02-18revision30909)
|
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
1.7.3