Ruby 1.9.2p136(2010-12-25revision30365)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

# ext/openssl/ossl_bn.c

Go to the documentation of this file.

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