• 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 27440 2010-04-22 08:21:01Z nobu $
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) == 0) {
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 

Generated on Wed Sep 8 2010 21:53:59 for Ruby by  doxygen 1.7.1