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