1/* 2 * $Id: ossl_bn.c 40113 2013-04-04 15:56:00Z nagachika $ 3 * 'OpenSSL for Ruby' project 4 * Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net> 5 * All rights reserved. 6 */ 7/* 8 * This program is licenced under the same licence as Ruby. 9 * (See the file 'LICENCE'.) 10 */ 11/* modified by Michal Rokos <m.rokos@sh.cvut.cz> */ 12#include "ossl.h" 13 14#define WrapBN(klass, obj, bn) do { \ 15 if (!(bn)) { \ 16 ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ 17 } \ 18 (obj) = Data_Wrap_Struct((klass), 0, BN_clear_free, (bn)); \ 19} while (0) 20 21#define GetBN(obj, bn) do { \ 22 Data_Get_Struct((obj), BIGNUM, (bn)); \ 23 if (!(bn)) { \ 24 ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \ 25 } \ 26} while (0) 27 28#define SafeGetBN(obj, bn) do { \ 29 OSSL_Check_Kind((obj), cBN); \ 30 GetBN((obj), (bn)); \ 31} while (0) 32 33/* 34 * Classes 35 */ 36VALUE cBN; 37VALUE eBNError; 38 39/* 40 * Public 41 */ 42VALUE 43ossl_bn_new(const BIGNUM *bn) 44{ 45 BIGNUM *newbn; 46 VALUE obj; 47 48 newbn = bn ? BN_dup(bn) : BN_new(); 49 if (!newbn) { 50 ossl_raise(eBNError, NULL); 51 } 52 WrapBN(cBN, obj, newbn); 53 54 return obj; 55} 56 57BIGNUM * 58GetBNPtr(VALUE obj) 59{ 60 BIGNUM *bn = NULL; 61 62 if (RTEST(rb_obj_is_kind_of(obj, cBN))) { 63 GetBN(obj, bn); 64 } else switch (TYPE(obj)) { 65 case T_FIXNUM: 66 case T_BIGNUM: 67 obj = rb_String(obj); 68 if (!BN_dec2bn(&bn, StringValuePtr(obj))) { 69 ossl_raise(eBNError, NULL); 70 } 71 WrapBN(cBN, obj, bn); /* Handle potencial mem leaks */ 72 break; 73 case T_NIL: 74 break; 75 default: 76 ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN"); 77 } 78 return bn; 79} 80 81/* 82 * Private 83 */ 84/* 85 * BN_CTX - is used in more difficult math. ops 86 * (Why just 1? Because Ruby itself isn't thread safe, 87 * we don't need to care about threads) 88 */ 89BN_CTX *ossl_bn_ctx; 90 91static VALUE 92ossl_bn_alloc(VALUE klass) 93{ 94 BIGNUM *bn; 95 VALUE obj; 96 97 if (!(bn = BN_new())) { 98 ossl_raise(eBNError, NULL); 99 } 100 WrapBN(klass, obj, bn); 101 102 return obj; 103} 104 105/* 106 * call-seq: 107 * BN.new => aBN 108 * BN.new(bn) => aBN 109 * BN.new(string) => aBN 110 * BN.new(string, 0 | 2 | 10 | 16) => aBN 111 */ 112static VALUE 113ossl_bn_initialize(int argc, VALUE *argv, VALUE self) 114{ 115 BIGNUM *bn; 116 VALUE str, bs; 117 int base = 10; 118 119 if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) { 120 base = NUM2INT(bs); 121 } 122 123 if (RTEST(rb_obj_is_kind_of(str, cBN))) { 124 BIGNUM *other; 125 126 GetBN(self, bn); 127 GetBN(str, other); /* Safe - we checked kind_of? above */ 128 if (!BN_copy(bn, other)) { 129 ossl_raise(eBNError, NULL); 130 } 131 return self; 132 } 133 134 StringValue(str); 135 GetBN(self, bn); 136 switch (base) { 137 case 0: 138 if (!BN_mpi2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) { 139 ossl_raise(eBNError, NULL); 140 } 141 break; 142 case 2: 143 if (!BN_bin2bn((unsigned char *)RSTRING_PTR(str), RSTRING_LENINT(str), bn)) { 144 ossl_raise(eBNError, NULL); 145 } 146 break; 147 case 10: 148 if (!BN_dec2bn(&bn, RSTRING_PTR(str))) { 149 ossl_raise(eBNError, NULL); 150 } 151 break; 152 case 16: 153 if (!BN_hex2bn(&bn, RSTRING_PTR(str))) { 154 ossl_raise(eBNError, NULL); 155 } 156 break; 157 default: 158 ossl_raise(rb_eArgError, "invalid radix %d", base); 159 } 160 return self; 161} 162 163/* 164 * call-seq: 165 * bn.to_s => string 166 * bn.to_s(base) => string 167 * 168 * === Parameters 169 * * +base+ - integer 170 * * * Valid values: 171 * * * * 0 - MPI 172 * * * * 2 - binary 173 * * * * 10 - the default 174 * * * * 16 - hex 175 */ 176static VALUE 177ossl_bn_to_s(int argc, VALUE *argv, VALUE self) 178{ 179 BIGNUM *bn; 180 VALUE str, bs; 181 int base = 10, len; 182 char *buf; 183 184 if (rb_scan_args(argc, argv, "01", &bs) == 1) { 185 base = NUM2INT(bs); 186 } 187 GetBN(self, bn); 188 switch (base) { 189 case 0: 190 len = BN_bn2mpi(bn, NULL); 191 str = rb_str_new(0, len); 192 if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len) 193 ossl_raise(eBNError, NULL); 194 break; 195 case 2: 196 len = BN_num_bytes(bn); 197 str = rb_str_new(0, len); 198 if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len) 199 ossl_raise(eBNError, NULL); 200 break; 201 case 10: 202 if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL); 203 str = ossl_buf2str(buf, rb_long2int(strlen(buf))); 204 break; 205 case 16: 206 if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL); 207 str = ossl_buf2str(buf, rb_long2int(strlen(buf))); 208 break; 209 default: 210 ossl_raise(rb_eArgError, "invalid radix %d", base); 211 } 212 213 return str; 214} 215 216/* 217 * call-seq: 218 * bn.to_i => integer 219 */ 220static VALUE 221ossl_bn_to_i(VALUE self) 222{ 223 BIGNUM *bn; 224 char *txt; 225 VALUE num; 226 227 GetBN(self, bn); 228 229 if (!(txt = BN_bn2dec(bn))) { 230 ossl_raise(eBNError, NULL); 231 } 232 num = rb_cstr_to_inum(txt, 10, Qtrue); 233 OPENSSL_free(txt); 234 235 return num; 236} 237 238static VALUE 239ossl_bn_to_bn(VALUE self) 240{ 241 return self; 242} 243 244static VALUE 245ossl_bn_coerce(VALUE self, VALUE other) 246{ 247 switch(TYPE(other)) { 248 case T_STRING: 249 self = ossl_bn_to_s(0, NULL, self); 250 break; 251 case T_FIXNUM: 252 case T_BIGNUM: 253 self = ossl_bn_to_i(self); 254 break; 255 default: 256 if (!RTEST(rb_obj_is_kind_of(other, cBN))) { 257 ossl_raise(rb_eTypeError, "Don't know how to coerce"); 258 } 259 } 260 return rb_assoc_new(other, self); 261} 262 263#define BIGNUM_BOOL1(func) \ 264 /* \ 265 * call-seq: \ 266 * bn.##func -> true | false \ 267 * \ 268 */ \ 269 static VALUE \ 270 ossl_bn_##func(VALUE self) \ 271 { \ 272 BIGNUM *bn; \ 273 GetBN(self, bn); \ 274 if (BN_##func(bn)) { \ 275 return Qtrue; \ 276 } \ 277 return Qfalse; \ 278 } 279BIGNUM_BOOL1(is_zero) 280BIGNUM_BOOL1(is_one) 281BIGNUM_BOOL1(is_odd) 282 283#define BIGNUM_1c(func) \ 284 /* \ 285 * call-seq: \ 286 * bn.##func -> aBN \ 287 * \ 288 */ \ 289 static VALUE \ 290 ossl_bn_##func(VALUE self) \ 291 { \ 292 BIGNUM *bn, *result; \ 293 VALUE obj; \ 294 GetBN(self, bn); \ 295 if (!(result = BN_new())) { \ 296 ossl_raise(eBNError, NULL); \ 297 } \ 298 if (!BN_##func(result, bn, ossl_bn_ctx)) { \ 299 BN_free(result); \ 300 ossl_raise(eBNError, NULL); \ 301 } \ 302 WrapBN(CLASS_OF(self), obj, result); \ 303 return obj; \ 304 } 305BIGNUM_1c(sqr) 306 307#define BIGNUM_2(func) \ 308 /* \ 309 * call-seq: \ 310 * bn.##func(bn2) -> aBN \ 311 * \ 312 */ \ 313 static VALUE \ 314 ossl_bn_##func(VALUE self, VALUE other) \ 315 { \ 316 BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ 317 VALUE obj; \ 318 GetBN(self, bn1); \ 319 if (!(result = BN_new())) { \ 320 ossl_raise(eBNError, NULL); \ 321 } \ 322 if (!BN_##func(result, bn1, bn2)) { \ 323 BN_free(result); \ 324 ossl_raise(eBNError, NULL); \ 325 } \ 326 WrapBN(CLASS_OF(self), obj, result); \ 327 return obj; \ 328 } 329BIGNUM_2(add) 330BIGNUM_2(sub) 331 332#define BIGNUM_2c(func) \ 333 /* \ 334 * call-seq: \ 335 * bn.##func(bn2) -> aBN \ 336 * \ 337 */ \ 338 static VALUE \ 339 ossl_bn_##func(VALUE self, VALUE other) \ 340 { \ 341 BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \ 342 VALUE obj; \ 343 GetBN(self, bn1); \ 344 if (!(result = BN_new())) { \ 345 ossl_raise(eBNError, NULL); \ 346 } \ 347 if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \ 348 BN_free(result); \ 349 ossl_raise(eBNError, NULL); \ 350 } \ 351 WrapBN(CLASS_OF(self), obj, result); \ 352 return obj; \ 353 } 354BIGNUM_2c(mul) 355BIGNUM_2c(mod) 356BIGNUM_2c(exp) 357BIGNUM_2c(gcd) 358BIGNUM_2c(mod_sqr) 359BIGNUM_2c(mod_inverse) 360 361/* 362 * call-seq: 363 * bn1 / bn2 => [result, remainder] 364 */ 365static VALUE 366ossl_bn_div(VALUE self, VALUE other) 367{ 368 BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2; 369 VALUE obj1, obj2; 370 371 GetBN(self, bn1); 372 373 if (!(r1 = BN_new())) { 374 ossl_raise(eBNError, NULL); 375 } 376 if (!(r2 = BN_new())) { 377 BN_free(r1); 378 ossl_raise(eBNError, NULL); 379 } 380 if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) { 381 BN_free(r1); 382 BN_free(r2); 383 ossl_raise(eBNError, NULL); 384 } 385 WrapBN(CLASS_OF(self), obj1, r1); 386 WrapBN(CLASS_OF(self), obj2, r2); 387 388 return rb_ary_new3(2, obj1, obj2); 389} 390 391#define BIGNUM_3c(func) \ 392 /* \ 393 * call-seq: \ 394 * bn.##func(bn1, bn2) -> aBN \ 395 * \ 396 */ \ 397 static VALUE \ 398 ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \ 399 { \ 400 BIGNUM *bn1, *bn2 = GetBNPtr(other1); \ 401 BIGNUM *bn3 = GetBNPtr(other2), *result; \ 402 VALUE obj; \ 403 GetBN(self, bn1); \ 404 if (!(result = BN_new())) { \ 405 ossl_raise(eBNError, NULL); \ 406 } \ 407 if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \ 408 BN_free(result); \ 409 ossl_raise(eBNError, NULL); \ 410 } \ 411 WrapBN(CLASS_OF(self), obj, result); \ 412 return obj; \ 413 } 414BIGNUM_3c(mod_add) 415BIGNUM_3c(mod_sub) 416BIGNUM_3c(mod_mul) 417BIGNUM_3c(mod_exp) 418 419#define BIGNUM_BIT(func) \ 420 /* \ 421 * call-seq: \ 422 * bn.##func(bit) -> self \ 423 * \ 424 */ \ 425 static VALUE \ 426 ossl_bn_##func(VALUE self, VALUE bit) \ 427 { \ 428 BIGNUM *bn; \ 429 GetBN(self, bn); \ 430 if (!BN_##func(bn, NUM2INT(bit))) { \ 431 ossl_raise(eBNError, NULL); \ 432 } \ 433 return self; \ 434 } 435BIGNUM_BIT(set_bit) 436BIGNUM_BIT(clear_bit) 437BIGNUM_BIT(mask_bits) 438 439/* 440 * call-seq: 441 * bn.bit_set?(bit) => true | false 442 */ 443static VALUE 444ossl_bn_is_bit_set(VALUE self, VALUE bit) 445{ 446 int b; 447 BIGNUM *bn; 448 449 b = NUM2INT(bit); 450 GetBN(self, bn); 451 if (BN_is_bit_set(bn, b)) { 452 return Qtrue; 453 } 454 return Qfalse; 455} 456 457#define BIGNUM_SHIFT(func) \ 458 /* \ 459 * call-seq: \ 460 * bn.##func(bits) -> aBN \ 461 * \ 462 */ \ 463 static VALUE \ 464 ossl_bn_##func(VALUE self, VALUE bits) \ 465 { \ 466 BIGNUM *bn, *result; \ 467 int b; \ 468 VALUE obj; \ 469 b = NUM2INT(bits); \ 470 GetBN(self, bn); \ 471 if (!(result = BN_new())) { \ 472 ossl_raise(eBNError, NULL); \ 473 } \ 474 if (!BN_##func(result, bn, b)) { \ 475 BN_free(result); \ 476 ossl_raise(eBNError, NULL); \ 477 } \ 478 WrapBN(CLASS_OF(self), obj, result); \ 479 return obj; \ 480 } 481BIGNUM_SHIFT(lshift) 482BIGNUM_SHIFT(rshift) 483 484#define BIGNUM_SELF_SHIFT(func) \ 485 /* \ 486 * call-seq: \ 487 * bn.##func!(bits) -> self \ 488 * \ 489 */ \ 490 static VALUE \ 491 ossl_bn_self_##func(VALUE self, VALUE bits) \ 492 { \ 493 BIGNUM *bn; \ 494 int b; \ 495 b = NUM2INT(bits); \ 496 GetBN(self, bn); \ 497 if (!BN_##func(bn, bn, b)) \ 498 ossl_raise(eBNError, NULL); \ 499 return self; \ 500 } 501BIGNUM_SELF_SHIFT(lshift) 502BIGNUM_SELF_SHIFT(rshift) 503 504#define BIGNUM_RAND(func) \ 505 /* \ 506 * call-seq: \ 507 * BN.##func(bits [, fill [, odd]]) -> aBN \ 508 * \ 509 */ \ 510 static VALUE \ 511 ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \ 512 { \ 513 BIGNUM *result; \ 514 int bottom = 0, top = 0, b; \ 515 VALUE bits, fill, odd, obj; \ 516 \ 517 switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \ 518 case 3: \ 519 bottom = (odd == Qtrue) ? 1 : 0; \ 520 /* FALLTHROUGH */ \ 521 case 2: \ 522 top = NUM2INT(fill); \ 523 } \ 524 b = NUM2INT(bits); \ 525 if (!(result = BN_new())) { \ 526 ossl_raise(eBNError, NULL); \ 527 } \ 528 if (!BN_##func(result, b, top, bottom)) { \ 529 BN_free(result); \ 530 ossl_raise(eBNError, NULL); \ 531 } \ 532 WrapBN(klass, obj, result); \ 533 return obj; \ 534 } 535BIGNUM_RAND(rand) 536BIGNUM_RAND(pseudo_rand) 537 538#define BIGNUM_RAND_RANGE(func) \ 539 /* \ 540 * call-seq: \ 541 * BN.##func(range) -> aBN \ 542 * \ 543 */ \ 544 static VALUE \ 545 ossl_bn_s_##func##_range(VALUE klass, VALUE range) \ 546 { \ 547 BIGNUM *bn = GetBNPtr(range), *result; \ 548 VALUE obj; \ 549 if (!(result = BN_new())) { \ 550 ossl_raise(eBNError, NULL); \ 551 } \ 552 if (!BN_##func##_range(result, bn)) { \ 553 BN_free(result); \ 554 ossl_raise(eBNError, NULL); \ 555 } \ 556 WrapBN(klass, obj, result); \ 557 return obj; \ 558 } 559BIGNUM_RAND_RANGE(rand) 560BIGNUM_RAND_RANGE(pseudo_rand) 561 562/* 563 * call-seq: 564 * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn 565 * 566 * === Parameters 567 * * +bits+ - integer 568 * * +safe+ - boolean 569 * * +add+ - BN 570 * * +rem+ - BN 571 */ 572static VALUE 573ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass) 574{ 575 BIGNUM *add = NULL, *rem = NULL, *result; 576 int safe = 1, num; 577 VALUE vnum, vsafe, vadd, vrem, obj; 578 579 rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem); 580 581 num = NUM2INT(vnum); 582 583 if (vsafe == Qfalse) { 584 safe = 0; 585 } 586 if (!NIL_P(vadd)) { 587 add = GetBNPtr(vadd); 588 rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem); 589 } 590 if (!(result = BN_new())) { 591 ossl_raise(eBNError, NULL); 592 } 593 if (!BN_generate_prime(result, num, safe, add, rem, NULL, NULL)) { 594 BN_free(result); 595 ossl_raise(eBNError, NULL); 596 } 597 WrapBN(klass, obj, result); 598 599 return obj; 600} 601 602#define BIGNUM_NUM(func) \ 603 /* \ 604 * call-seq: \ 605 * bn.##func -> integer \ 606 * \ 607 */ \ 608 static VALUE \ 609 ossl_bn_##func(VALUE self) \ 610 { \ 611 BIGNUM *bn; \ 612 GetBN(self, bn); \ 613 return INT2FIX(BN_##func(bn)); \ 614 } 615BIGNUM_NUM(num_bytes) 616BIGNUM_NUM(num_bits) 617 618static VALUE 619ossl_bn_copy(VALUE self, VALUE other) 620{ 621 BIGNUM *bn1, *bn2; 622 623 rb_check_frozen(self); 624 625 if (self == other) return self; 626 627 GetBN(self, bn1); 628 bn2 = GetBNPtr(other); 629 630 if (!BN_copy(bn1, bn2)) { 631 ossl_raise(eBNError, NULL); 632 } 633 return self; 634} 635 636#define BIGNUM_CMP(func) \ 637 /* \ 638 * call-seq: \ 639 * bn.##func(bn2) -> integer \ 640 * \ 641 */ \ 642 static VALUE \ 643 ossl_bn_##func(VALUE self, VALUE other) \ 644 { \ 645 BIGNUM *bn1, *bn2 = GetBNPtr(other); \ 646 GetBN(self, bn1); \ 647 return INT2FIX(BN_##func(bn1, bn2)); \ 648 } 649BIGNUM_CMP(cmp) 650BIGNUM_CMP(ucmp) 651 652static VALUE 653ossl_bn_eql(VALUE self, VALUE other) 654{ 655 if (ossl_bn_cmp(self, other) == INT2FIX(0)) { 656 return Qtrue; 657 } 658 return Qfalse; 659} 660 661/* 662 * call-seq: 663 * bn.prime? => true | false 664 * bn.prime?(checks) => true | false 665 * 666 * === Parameters 667 * * +checks+ - integer 668 */ 669static VALUE 670ossl_bn_is_prime(int argc, VALUE *argv, VALUE self) 671{ 672 BIGNUM *bn; 673 VALUE vchecks; 674 int checks = BN_prime_checks; 675 676 if (rb_scan_args(argc, argv, "01", &vchecks) == 1) { 677 checks = NUM2INT(vchecks); 678 } 679 GetBN(self, bn); 680 switch (BN_is_prime(bn, checks, NULL, ossl_bn_ctx, NULL)) { 681 case 1: 682 return Qtrue; 683 case 0: 684 return Qfalse; 685 default: 686 ossl_raise(eBNError, NULL); 687 } 688 /* not reachable */ 689 return Qnil; 690} 691 692/* 693 * call-seq: 694 * bn.prime_fasttest? => true | false 695 * bn.prime_fasttest?(checks) => true | false 696 * bn.prime_fasttest?(checks, trial_div) => true | false 697 * 698 * === Parameters 699 * * +checks+ - integer 700 * * +trial_div+ - boolean 701 */ 702static VALUE 703ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self) 704{ 705 BIGNUM *bn; 706 VALUE vchecks, vtrivdiv; 707 int checks = BN_prime_checks, do_trial_division = 1; 708 709 rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv); 710 711 if (!NIL_P(vchecks)) { 712 checks = NUM2INT(vchecks); 713 } 714 GetBN(self, bn); 715 /* handle true/false */ 716 if (vtrivdiv == Qfalse) { 717 do_trial_division = 0; 718 } 719 switch (BN_is_prime_fasttest(bn, checks, NULL, ossl_bn_ctx, NULL, do_trial_division)) { 720 case 1: 721 return Qtrue; 722 case 0: 723 return Qfalse; 724 default: 725 ossl_raise(eBNError, NULL); 726 } 727 /* not reachable */ 728 return Qnil; 729} 730 731/* 732 * INIT 733 * (NOTE: ordering of methods is the same as in 'man bn') 734 */ 735void 736Init_ossl_bn() 737{ 738#if 0 739 mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */ 740#endif 741 742 if (!(ossl_bn_ctx = BN_CTX_new())) { 743 ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX"); 744 } 745 746 eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError); 747 748 cBN = rb_define_class_under(mOSSL, "BN", rb_cObject); 749 750 rb_define_alloc_func(cBN, ossl_bn_alloc); 751 rb_define_method(cBN, "initialize", ossl_bn_initialize, -1); 752 753 rb_define_copy_func(cBN, ossl_bn_copy); 754 rb_define_method(cBN, "copy", ossl_bn_copy, 1); 755 756 /* swap (=coerce?) */ 757 758 rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0); 759 rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0); 760 /* num_bits_word */ 761 762 rb_define_method(cBN, "+", ossl_bn_add, 1); 763 rb_define_method(cBN, "-", ossl_bn_sub, 1); 764 rb_define_method(cBN, "*", ossl_bn_mul, 1); 765 rb_define_method(cBN, "sqr", ossl_bn_sqr, 0); 766 rb_define_method(cBN, "/", ossl_bn_div, 1); 767 rb_define_method(cBN, "%", ossl_bn_mod, 1); 768 /* nnmod */ 769 770 rb_define_method(cBN, "mod_add", ossl_bn_mod_add, 2); 771 rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2); 772 rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2); 773 rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1); 774 rb_define_method(cBN, "**", ossl_bn_exp, 1); 775 rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2); 776 rb_define_method(cBN, "gcd", ossl_bn_gcd, 1); 777 778 /* add_word 779 * sub_word 780 * mul_word 781 * div_word 782 * mod_word */ 783 784 rb_define_method(cBN, "cmp", ossl_bn_cmp, 1); 785 rb_define_alias(cBN, "<=>", "cmp"); 786 rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1); 787 rb_define_method(cBN, "eql?", ossl_bn_eql, 1); 788 rb_define_alias(cBN, "==", "eql?"); 789 rb_define_alias(cBN, "===", "eql?"); 790 rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0); 791 rb_define_method(cBN, "one?", ossl_bn_is_one, 0); 792 /* is_word */ 793 rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0); 794 795 /* zero 796 * one 797 * value_one - DON'T IMPL. 798 * set_word 799 * get_word */ 800 801 rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1); 802 rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1); 803 rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1); 804 rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1); 805 806 rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1); 807 rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1); 808 809 rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1); 810 rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1); 811 rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1); 812 rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1); 813 rb_define_method(cBN, "<<", ossl_bn_lshift, 1); 814 rb_define_method(cBN, ">>", ossl_bn_rshift, 1); 815 rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1); 816 rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1); 817 /* lshift1 - DON'T IMPL. */ 818 /* rshift1 - DON'T IMPL. */ 819 820 /* 821 * bn2bin 822 * bin2bn 823 * bn2hex 824 * bn2dec 825 * hex2bn 826 * dec2bn - all these are implemented in ossl_bn_initialize, and ossl_bn_to_s 827 * print - NOT IMPL. 828 * print_fp - NOT IMPL. 829 * bn2mpi 830 * mpi2bn 831 */ 832 rb_define_method(cBN, "to_s", ossl_bn_to_s, -1); 833 rb_define_method(cBN, "to_i", ossl_bn_to_i, 0); 834 rb_define_alias(cBN, "to_int", "to_i"); 835 rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0); 836 rb_define_method(cBN, "coerce", ossl_bn_coerce, 1); 837 838 /* 839 * TODO: 840 * But how to: from_bin, from_mpi? PACK? 841 * to_bin 842 * to_mpi 843 */ 844 845 rb_define_method(cBN, "mod_inverse", ossl_bn_mod_inverse, 1); 846 847 /* RECiProcal 848 * MONTgomery */ 849 850 /* 851 * TODO: 852 * Where to belong these? 853 */ 854 rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1); 855} 856 857