|
Ruby 1.9.2p290(2011-07-09revision32553)
|
00001 /* 00002 * $Id: ossl_bn.c 29794 2010-11-15 11:43:42Z yugui $ 00003 * 'OpenSSL for Ruby' project 00004 * Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net> 00005 * All rights reserved. 00006 */ 00007 /* 00008 * This program is licenced under the same licence as Ruby. 00009 * (See the file 'LICENCE'.) 00010 */ 00011 /* modified by Michal Rokos <m.rokos@sh.cvut.cz> */ 00012 #include "ossl.h" 00013 00014 #define WrapBN(klass, obj, bn) do { \ 00015 if (!bn) { \ 00016 ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ 00017 } \ 00018 obj = Data_Wrap_Struct(klass, 0, BN_clear_free, bn); \ 00019 } while (0) 00020 00021 #define GetBN(obj, bn) do { \ 00022 Data_Get_Struct(obj, BIGNUM, bn); \ 00023 if (!bn) { \ 00024 ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ 00025 } \ 00026 } while (0) 00027 00028 #define SafeGetBN(obj, bn) do { \ 00029 OSSL_Check_Kind(obj, cBN); \ 00030 GetBN(obj, bn); \ 00031 } while (0) 00032 00033 /* 00034 * Classes 00035 */ 00036 VALUE cBN; 00037 VALUE eBNError; 00038 00039 /* 00040 * Public 00041 */ 00042 VALUE 00043 ossl_bn_new(const BIGNUM *bn) 00044 { 00045 BIGNUM *newbn; 00046 VALUE obj; 00047 00048 newbn = bn ? BN_dup(bn) : BN_new(); 00049 if (!newbn) { 00050 ossl_raise(eBNError, NULL); 00051 } 00052 WrapBN(cBN, obj, newbn); 00053 00054 return obj; 00055 } 00056 00057 BIGNUM * 00058 GetBNPtr(VALUE obj) 00059 { 00060 BIGNUM *bn = NULL; 00061 00062 if (RTEST(rb_obj_is_kind_of(obj, cBN))) { 00063 GetBN(obj, bn); 00064 } else switch (TYPE(obj)) { 00065 case T_FIXNUM: 00066 case T_BIGNUM: 00067 obj = rb_String(obj); 00068 if (!BN_dec2bn(&bn, StringValuePtr(obj))) { 00069 ossl_raise(eBNError, NULL); 00070 } 00071 WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */ 00072 break; 00073 default: 00074 ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN"); 00075 } 00076 return bn; 00077 } 00078 00079 /* 00080 * Private 00081 */ 00082 /* 00083 * BN_CTX - is used in more difficult math. ops 00084 * (Why just 1? Because Ruby itself isn't thread safe, 00085 * we don't need to care about threads) 00086 */ 00087 BN_CTX *ossl_bn_ctx; 00088 00089 static VALUE 00090 ossl_bn_alloc(VALUE klass) 00091 { 00092 BIGNUM *bn; 00093 VALUE obj; 00094 00095 if (!(bn = BN_new())) { 00096 ossl_raise(eBNError, NULL); 00097 } 00098 WrapBN(klass, obj, bn); 00099 00100 return obj; 00101 } 00102 00103 /* 00104 * call-seq: 00105 * BN.new => aBN 00106 * BN.new(bn) => aBN 00107 * BN.new(string) => aBN 00108 * BN.new(string, 0 | 2 | 10 | 16) => aBN 00109 */ 00110 static VALUE 00111 ossl_bn_initialize(int argc, VALUE *argv, VALUE self) 00112 { 00113 BIGNUM *bn; 00114 VALUE str, bs; 00115 int base = 10; 00116 00117 if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) { 00118 base = NUM2INT(bs); 00119 } 00120 StringValue(str); 00121 GetBN(self, bn); 00122 if (RTEST(rb_obj_is_kind_of(str, cBN))) { 00123 BIGNUM *other; 00124 00125 GetBN(str, other); /* Safe - we checked kind_of? above */ 00126 if (!BN_copy(bn, other)) { 00127 ossl_raise(eBNError, NULL); 00128 } 00129 return self; 00130 } 00131 00132 switch (base) { 00133 case 0: 00134 if (!BN_mpi2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str), bn)) { 00135 ossl_raise(eBNError, NULL); 00136 } 00137 break; 00138 case 2: 00139 if (!BN_bin2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LEN(str), bn)) { 00140 ossl_raise(eBNError, NULL); 00141 } 00142 break; 00143 case 10: 00144 if (!BN_dec2bn(&bn, RSTRING_PTR(str))) { 00145 ossl_raise(eBNError, NULL); 00146 } 00147 break; 00148 case 16: 00149 if (!BN_hex2bn(&bn, RSTRING_PTR(str))) { 00150 ossl_raise(eBNError, NULL); 00151 } 00152 break; 00153 default: 00154 ossl_raise(rb_eArgError, "invalid radix %d", base); 00155 } 00156 return self; 00157 } 00158 00159 /* 00160 * call-seq: 00161 * bn.to_s => string 00162 * bn.to_s(base) => string 00163 * 00164 * === Parameters 00165 * * +base+ - integer 00166 * * * Valid values: 00167 * * * * 0 - MPI 00168 * * * * 2 - binary 00169 * * * * 10 - the default 00170 * * * * 16 - hex 00171 */ 00172 static VALUE 00173 ossl_bn_to_s(int argc, VALUE *argv, VALUE self) 00174 { 00175 BIGNUM *bn; 00176 VALUE str, bs; 00177 int base = 10, len; 00178 char *buf; 00179 00180 if (rb_scan_args(argc, argv, "01", &bs) == 1) { 00181 base = NUM2INT(bs); 00182 } 00183 GetBN(self, bn); 00184 switch (base) { 00185 case 0: 00186 len = BN_bn2mpi(bn, NULL); 00187 str = rb_str_new(0, len); 00188 if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len) 00189 ossl_raise(eBNError, NULL); 00190 break; 00191 case 2: 00192 len = BN_num_bytes(bn); 00193 str = rb_str_new(0, len); 00194 if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len) 00195 ossl_raise(eBNError, NULL); 00196 break; 00197 case 10: 00198 if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL); 00199 str = ossl_buf2str(buf, strlen(buf)); 00200 break; 00201 case 16: 00202 if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL); 00203 str = ossl_buf2str(buf, strlen(buf)); 00204 break; 00205 default: 00206 ossl_raise(rb_eArgError, "invalid radix %d", base); 00207 } 00208 00209 return str; 00210 } 00211 00212 /* 00213 * call-seq: 00214 * bn.to_i => integer 00215 */ 00216 static VALUE 00217 ossl_bn_to_i(VALUE self) 00218 { 00219 BIGNUM *bn; 00220 char *txt; 00221 VALUE num; 00222 00223 GetBN(self, bn); 00224 00225 if (!(txt = BN_bn2dec(bn))) { 00226 ossl_raise(eBNError, NULL); 00227 } 00228 num = rb_cstr_to_inum(txt, 10, Qtrue); 00229 OPENSSL_free(txt); 00230 00231 return num; 00232 } 00233 00234 static VALUE 00235 ossl_bn_to_bn(VALUE self) 00236 { 00237 return self; 00238 } 00239 00240 static VALUE 00241 ossl_bn_coerce(VALUE self, VALUE other) 00242 { 00243 switch(TYPE(other)) { 00244 case T_STRING: 00245 self = ossl_bn_to_s(0, NULL, self); 00246 break; 00247 case T_FIXNUM: 00248 case T_BIGNUM: 00249 self = ossl_bn_to_i(self); 00250 break; 00251 default: 00252 if (!RTEST(rb_obj_is_kind_of(other, cBN))) { 00253 ossl_raise(rb_eTypeError, "Don't know how to coerce"); 00254 } 00255 } 00256 return rb_assoc_new(other, self); 00257 } 00258 00259 #define BIGNUM_BOOL1(func) \ 00260 /* \ 00261 * call-seq: \ 00262 * bn.##func -> true | false \ 00263 * \ 00264 */ \ 00265 static VALUE \ 00266 ossl_bn_##func(VALUE self) \ 00267 { \ 00268 BIGNUM *bn; \ 00269 GetBN(self, bn); \ 00270 if (BN_##func(bn)) { \ 00271 return Qtrue; \ 00272 } \ 00273 return Qfalse; \ 00274 } 00275 BIGNUM_BOOL1(is_zero) 00276 BIGNUM_BOOL1(is_one) 00277 BIGNUM_BOOL1(is_odd) 00278 00279 #define BIGNUM_1c(func) \ 00280 /* \ 00281 * call-seq: \ 00282 * bn.##func -> aBN \ 00283 * \ 00284 */ \ 00285 static VALUE \ 00286 ossl_bn_##func(VALUE self) \ 00287 { \ 00288 BIGNUM *bn, *result; \ 00289 VALUE obj; \ 00290 GetBN(self, bn); \ 00291 if (!(result = BN_new())) { \ 00292 ossl_raise(eBNError, NULL); \ 00293 } \ 00294 if (!BN_##func(result, bn, ossl_bn_ctx)) { \ 00295 BN_free(result); \ 00296 ossl_raise(eBNError, NULL); \ 00297 } \ 00298 WrapBN(CLASS_OF(self), obj, result); \ 00299 return obj; \ 00300 } 00301 BIGNUM_1c(sqr) 00302 00303 #define BIGNUM_2(func) \ 00304 /* \ 00305 * call-seq: \ 00306 * bn.##func(bn2) -> aBN \ 00307 * \ 00308 */ \ 00309 static VALUE \ 00310 ossl_bn_##func(VALUE self, VALUE other) \ 00311 { \ 00312 BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ 00313 VALUE obj; \ 00314 GetBN(self, bn1); \ 00315 if (!(result = BN_new())) { \ 00316 ossl_raise(eBNError, NULL); \ 00317 } \ 00318 if (!BN_##func(result, bn1, bn2)) { \ 00319 BN_free(result); \ 00320 ossl_raise(eBNError, NULL); \ 00321 } \ 00322 WrapBN(CLASS_OF(self), obj, result); \ 00323 return obj; \ 00324 } 00325 BIGNUM_2(add) 00326 BIGNUM_2(sub) 00327 00328 #define BIGNUM_2c(func) \ 00329 /* \ 00330 * call-seq: \ 00331 * bn.##func(bn2) -> aBN \ 00332 * \ 00333 */ \ 00334 static VALUE \ 00335 ossl_bn_##func(VALUE self, VALUE other) \ 00336 { \ 00337 BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ 00338 VALUE obj; \ 00339 GetBN(self, bn1); \ 00340 if (!(result = BN_new())) { \ 00341 ossl_raise(eBNError, NULL); \ 00342 } \ 00343 if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \ 00344 BN_free(result); \ 00345 ossl_raise(eBNError, NULL); \ 00346 } \ 00347 WrapBN(CLASS_OF(self), obj, result); \ 00348 return obj; \ 00349 } 00350 BIGNUM_2c(mul) 00351 BIGNUM_2c(mod) 00352 BIGNUM_2c(exp) 00353 BIGNUM_2c(gcd) 00354 BIGNUM_2c(mod_sqr) 00355 BIGNUM_2c(mod_inverse) 00356 00357 /* 00358 * call-seq: 00359 * bn1 / bn2 => [result, remainder] 00360 */ 00361 static VALUE 00362 ossl_bn_div(VALUE self, VALUE other) 00363 { 00364 BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2; 00365 VALUE obj1, obj2; 00366 00367 GetBN(self, bn1); 00368 00369 if (!(r1 = BN_new())) { 00370 ossl_raise(eBNError, NULL); 00371 } 00372 if (!(r2 = BN_new())) { 00373 BN_free(r1); 00374 ossl_raise(eBNError, NULL); 00375 } 00376 if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) { 00377 BN_free(r1); 00378 BN_free(r2); 00379 ossl_raise(eBNError, NULL); 00380 } 00381 WrapBN(CLASS_OF(self), obj1, r1); 00382 WrapBN(CLASS_OF(self), obj2, r2); 00383 00384 return rb_ary_new3(2, obj1, obj2); 00385 } 00386 00387 #define BIGNUM_3c(func) \ 00388 /* \ 00389 * call-seq: \ 00390 * bn.##func(bn1, bn2) -> aBN \ 00391 * \ 00392 */ \ 00393 static VALUE \ 00394 ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \ 00395 { \ 00396 BIGNUM *bn1, *bn2 = GetBNPtr(other1); \ 00397 BIGNUM *bn3 = GetBNPtr(other2), *result; \ 00398 VALUE obj; \ 00399 GetBN(self, bn1); \ 00400 if (!(result = BN_new())) { \ 00401 ossl_raise(eBNError, NULL); \ 00402 } \ 00403 if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \ 00404 BN_free(result); \ 00405 ossl_raise(eBNError, NULL); \ 00406 } \ 00407 WrapBN(CLASS_OF(self), obj, result); \ 00408 return obj; \ 00409 } 00410 BIGNUM_3c(mod_add) 00411 BIGNUM_3c(mod_sub) 00412 BIGNUM_3c(mod_mul) 00413 BIGNUM_3c(mod_exp) 00414 00415 #define BIGNUM_BIT(func) \ 00416 /* \ 00417 * call-seq: \ 00418 * bn.##func(bit) -> self \ 00419 * \ 00420 */ \ 00421 static VALUE \ 00422 ossl_bn_##func(VALUE self, VALUE bit) \ 00423 { \ 00424 BIGNUM *bn; \ 00425 GetBN(self, bn); \ 00426 if (!BN_##func(bn, NUM2INT(bit))) { \ 00427 ossl_raise(eBNError, NULL); \ 00428 } \ 00429 return self; \ 00430 } 00431 BIGNUM_BIT(set_bit) 00432 BIGNUM_BIT(clear_bit) 00433 BIGNUM_BIT(mask_bits) 00434 00435 /* 00436 * call-seq: 00437 * bn.bit_set?(bit) => true | false 00438 */ 00439 static VALUE 00440 ossl_bn_is_bit_set(VALUE self, VALUE bit) 00441 { 00442 int b; 00443 BIGNUM *bn; 00444 00445 b = NUM2INT(bit); 00446 GetBN(self, bn); 00447 if (BN_is_bit_set(bn, b)) { 00448 return Qtrue; 00449 } 00450 return Qfalse; 00451 } 00452 00453 #define BIGNUM_SHIFT(func) \ 00454 /* \ 00455 * call-seq: \ 00456 * bn.##func(bits) -> aBN \ 00457 * \ 00458 */ \ 00459 static VALUE \ 00460 ossl_bn_##func(VALUE self, VALUE bits) \ 00461 { \ 00462 BIGNUM *bn, *result; \ 00463 int b; \ 00464 VALUE obj; \ 00465 b = NUM2INT(bits); \ 00466 GetBN(self, bn); \ 00467 if (!(result = BN_new())) { \ 00468 ossl_raise(eBNError, NULL); \ 00469 } \ 00470 if (!BN_##func(result, bn, b)) { \ 00471 BN_free(result); \ 00472 ossl_raise(eBNError, NULL); \ 00473 } \ 00474 WrapBN(CLASS_OF(self), obj, result); \ 00475 return obj; \ 00476 } 00477 BIGNUM_SHIFT(lshift) 00478 BIGNUM_SHIFT(rshift) 00479 00480 #define BIGNUM_SELF_SHIFT(func) \ 00481 /* \ 00482 * call-seq: \ 00483 * bn.##func!(bits) -> self \ 00484 * \ 00485 */ \ 00486 static VALUE \ 00487 ossl_bn_self_##func(VALUE self, VALUE bits) \ 00488 { \ 00489 BIGNUM *bn; \ 00490 int b; \ 00491 b = NUM2INT(bits); \ 00492 GetBN(self, bn); \ 00493 if (!BN_##func(bn, bn, b)) \ 00494 ossl_raise(eBNError, NULL); \ 00495 return self; \ 00496 } 00497 BIGNUM_SELF_SHIFT(lshift) 00498 BIGNUM_SELF_SHIFT(rshift) 00499 00500 #define BIGNUM_RAND(func) \ 00501 /* \ 00502 * call-seq: \ 00503 * BN.##func(bits [, fill [, odd]]) -> aBN \ 00504 * \ 00505 */ \ 00506 static VALUE \ 00507 ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \ 00508 { \ 00509 BIGNUM *result; \ 00510 int bottom = 0, top = 0, b; \ 00511 VALUE bits, fill, odd, obj; \ 00512 \ 00513 switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \ 00514 case 3: \ 00515 bottom = (odd == Qtrue) ? 1 : 0; \ 00516 /* FALLTHROUGH */ \ 00517 case 2: \ 00518 top = NUM2INT(fill); \ 00519 } \ 00520 b = NUM2INT(bits); \ 00521 if (!(result = BN_new())) { \ 00522 ossl_raise(eBNError, NULL); \ 00523 } \ 00524 if (!BN_##func(result, b, top, bottom)) { \ 00525 BN_free(result); \ 00526 ossl_raise(eBNError, NULL); \ 00527 } \ 00528 WrapBN(klass, obj, result); \ 00529 return obj; \ 00530 } 00531 BIGNUM_RAND(rand) 00532 BIGNUM_RAND(pseudo_rand) 00533 00534 #define BIGNUM_RAND_RANGE(func) \ 00535 /* \ 00536 * call-seq: \ 00537 * BN.##func(range) -> aBN \ 00538 * \ 00539 */ \ 00540 static VALUE \ 00541 ossl_bn_s_##func##_range(VALUE klass, VALUE range) \ 00542 { \ 00543 BIGNUM *bn = GetBNPtr(range), *result; \ 00544 VALUE obj; \ 00545 if (!(result = BN_new())) { \ 00546 ossl_raise(eBNError, NULL); \ 00547 } \ 00548 if (!BN_##func##_range(result, bn)) { \ 00549 BN_free(result); \ 00550 ossl_raise(eBNError, NULL); \ 00551 } \ 00552 WrapBN(klass, obj, result); \ 00553 return obj; \ 00554 } 00555 BIGNUM_RAND_RANGE(rand) 00556 BIGNUM_RAND_RANGE(pseudo_rand) 00557 00558 /* 00559 * call-seq: 00560 * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn 00561 * 00562 * === Parameters 00563 * * +bits+ - integer 00564 * * +safe+ - boolean 00565 * * +add+ - BN 00566 * * +rem+ - BN 00567 */ 00568 static VALUE 00569 ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass) 00570 { 00571 BIGNUM *add = NULL, *rem = NULL, *result; 00572 int safe = 1, num; 00573 VALUE vnum, vsafe, vadd, vrem, obj; 00574 00575 rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem); 00576 00577 num = NUM2INT(vnum); 00578 00579 if (vsafe == Qfalse) { 00580 safe = 0; 00581 } 00582 if (!NIL_P(vadd)) { 00583 add = GetBNPtr(vadd); 00584 rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem); 00585 } 00586 if (!(result = BN_new())) { 00587 ossl_raise(eBNError, NULL); 00588 } 00589 if (!BN_generate_prime(result, num, safe, add, rem, NULL, NULL)) { 00590 BN_free(result); 00591 ossl_raise(eBNError, NULL); 00592 } 00593 WrapBN(klass, obj, result); 00594 00595 return obj; 00596 } 00597 00598 #define BIGNUM_NUM(func) \ 00599 /* \ 00600 * call-seq: \ 00601 * bn.##func -> integer \ 00602 * \ 00603 */ \ 00604 static VALUE \ 00605 ossl_bn_##func(VALUE self) \ 00606 { \ 00607 BIGNUM *bn; \ 00608 GetBN(self, bn); \ 00609 return INT2FIX(BN_##func(bn)); \ 00610 } 00611 BIGNUM_NUM(num_bytes) 00612 BIGNUM_NUM(num_bits) 00613 00614 static VALUE 00615 ossl_bn_copy(VALUE self, VALUE other) 00616 { 00617 BIGNUM *bn1, *bn2; 00618 00619 rb_check_frozen(self); 00620 00621 if (self == other) return self; 00622 00623 GetBN(self, bn1); 00624 bn2 = GetBNPtr(other); 00625 00626 if (!BN_copy(bn1, bn2)) { 00627 ossl_raise(eBNError, NULL); 00628 } 00629 return self; 00630 } 00631 00632 #define BIGNUM_CMP(func) \ 00633 /* \ 00634 * call-seq: \ 00635 * bn.##func(bn2) -> integer \ 00636 * \ 00637 */ \ 00638 static VALUE \ 00639 ossl_bn_##func(VALUE self, VALUE other) \ 00640 { \ 00641 BIGNUM *bn1, *bn2 = GetBNPtr(other); \ 00642 GetBN(self, bn1); \ 00643 return INT2FIX(BN_##func(bn1, bn2)); \ 00644 } 00645 BIGNUM_CMP(cmp) 00646 BIGNUM_CMP(ucmp) 00647 00648 static VALUE 00649 ossl_bn_eql(VALUE self, VALUE other) 00650 { 00651 if (ossl_bn_cmp(self, other) == INT2FIX(0)) { 00652 return Qtrue; 00653 } 00654 return Qfalse; 00655 } 00656 00657 /* 00658 * call-seq: 00659 * bn.prime? => true | false 00660 * bn.prime?(checks) => true | false 00661 * 00662 * === Parameters 00663 * * +checks+ - integer 00664 */ 00665 static VALUE 00666 ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) 00667 { 00668 BIGNUM *bn; 00669 VALUE vchecks; 00670 int checks = BN_prime_checks; 00671 00672 if (rb_scan_args(argc, argv, "01", &vchecks) == 1) { 00673 checks = NUM2INT(vchecks); 00674 } 00675 GetBN(self, bn); 00676 switch (BN_is_prime(bn, checks, NULL, ossl_bn_ctx, NULL)) { 00677 case 1: 00678 return Qtrue; 00679 case 0: 00680 return Qfalse; 00681 default: 00682 ossl_raise(eBNError, NULL); 00683 } 00684 /* not reachable */ 00685 return Qnil; 00686 } 00687 00688 /* 00689 * call-seq: 00690 * bn.prime_fasttest? => true | false 00691 * bn.prime_fasttest?(checks) => true | false 00692 * bn.prime_fasttest?(checks, trial_div) => true | false 00693 * 00694 * === Parameters 00695 * * +checks+ - integer 00696 * * +trial_div+ - boolean 00697 */ 00698 static VALUE 00699 ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) 00700 { 00701 BIGNUM *bn; 00702 VALUE vchecks, vtrivdiv; 00703 int checks = BN_prime_checks, do_trial_division = 1; 00704 00705 rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv); 00706 00707 if (!NIL_P(vchecks)) { 00708 checks = NUM2INT(vchecks); 00709 } 00710 GetBN(self, bn); 00711 /* handle true/false */ 00712 if (vtrivdiv == Qfalse) { 00713 do_trial_division = 0; 00714 } 00715 switch (BN_is_prime_fasttest(bn, checks, NULL, ossl_bn_ctx, NULL, do_trial_division)) { 00716 case 1: 00717 return Qtrue; 00718 case 0: 00719 return Qfalse; 00720 default: 00721 ossl_raise(eBNError, NULL); 00722 } 00723 /* not reachable */ 00724 return Qnil; 00725 } 00726 00727 /* 00728 * INIT 00729 * (NOTE: ordering of methods is the same as in 'man bn') 00730 */ 00731 void 00732 Init_ossl_bn() 00733 { 00734 #if 0 /* let rdoc know about mOSSL */ 00735 mOSSL = rb_define_module("OpenSSL"); 00736 #endif 00737 00738 if (!(ossl_bn_ctx = BN_CTX_new())) { 00739 ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); 00740 } 00741 00742 eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); 00743 00744 cBN = rb_define_class_under(mOSSL, "BN", rb_cObject); 00745 00746 rb_define_alloc_func(cBN, ossl_bn_alloc); 00747 rb_define_method(cBN, "initialize", ossl_bn_initialize, -1); 00748 00749 rb_define_copy_func(cBN, ossl_bn_copy); 00750 rb_define_method(cBN, "copy", ossl_bn_copy, 1); 00751 00752 /* swap (=coerce?) */ 00753 00754 rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0); 00755 rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0); 00756 /* num_bits_word */ 00757 00758 rb_define_method(cBN, "+", ossl_bn_add, 1); 00759 rb_define_method(cBN, "-", ossl_bn_sub, 1); 00760 rb_define_method(cBN, "*", ossl_bn_mul, 1); 00761 rb_define_method(cBN, "sqr", ossl_bn_sqr, 0); 00762 rb_define_method(cBN, "/", ossl_bn_div, 1); 00763 rb_define_method(cBN, "%", ossl_bn_mod, 1); 00764 /* nnmod */ 00765 00766 rb_define_method(cBN, "mod_add", ossl_bn_mod_add, 2); 00767 rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2); 00768 rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2); 00769 rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1); 00770 rb_define_method(cBN, "**", ossl_bn_exp, 1); 00771 rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2); 00772 rb_define_method(cBN, "gcd", ossl_bn_gcd, 1); 00773 00774 /* add_word 00775 * sub_word 00776 * mul_word 00777 * div_word 00778 * mod_word */ 00779 00780 rb_define_method(cBN, "cmp", ossl_bn_cmp, 1); 00781 rb_define_alias(cBN, "<=>", "cmp"); 00782 rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); 00783 rb_define_method(cBN, "eql?", ossl_bn_eql, 1); 00784 rb_define_alias(cBN, "==", "eql?"); 00785 rb_define_alias(cBN, "===", "eql?"); 00786 rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); 00787 rb_define_method(cBN, "one?", ossl_bn_is_one, 0); 00788 /* is_word */ 00789 rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0); 00790 00791 /* zero 00792 * one 00793 * value_one - DON'T IMPL. 00794 * set_word 00795 * get_word */ 00796 00797 rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1); 00798 rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1); 00799 rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); 00800 rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1); 00801 00802 rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1); 00803 rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1); 00804 00805 rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1); 00806 rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1); 00807 rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1); 00808 rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1); 00809 rb_define_method(cBN, "<<", ossl_bn_lshift, 1); 00810 rb_define_method(cBN, ">>", ossl_bn_rshift, 1); 00811 rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1); 00812 rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1); 00813 /* lshift1 - DON'T IMPL. */ 00814 /* rshift1 - DON'T IMPL. */ 00815 00816 /* 00817 * bn2bin 00818 * bin2bn 00819 * bn2hex 00820 * bn2dec 00821 * hex2bn 00822 * dec2bn - all these are implemented in ossl_bn_initialize, and ossl_bn_to_s 00823 * print - NOT IMPL. 00824 * print_fp - NOT IMPL. 00825 * bn2mpi 00826 * mpi2bn 00827 */ 00828 rb_define_method(cBN, "to_s", ossl_bn_to_s, -1); 00829 rb_define_method(cBN, "to_i", ossl_bn_to_i, 0); 00830 rb_define_alias(cBN, "to_int", "to_i"); 00831 rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0); 00832 rb_define_method(cBN, "coerce", ossl_bn_coerce, 1); 00833 00834 /* 00835 * TODO: 00836 * But how to: from_bin, from_mpi? PACK? 00837 * to_bin 00838 * to_mpi 00839 */ 00840 00841 rb_define_method(cBN, "mod_inverse", ossl_bn_mod_inverse, 1); 00842 00843 /* RECiProcal 00844 * MONTgomery */ 00845 00846 /* 00847 * TODO: 00848 * Where to belong these? 00849 */ 00850 rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1); 00851 } 00852 00853
1.7.3