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