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