Ruby  2.0.0p247(2013-06-27revision41674)
ext/openssl/ossl_bn.c
Go to the documentation of this file.
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