|
Ruby 1.9.2p290(2011-07-09revision32553)
|
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
1.7.3