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