Ruby  2.4.2p198(2017-09-14revision59899)
ossl_bn.c
Go to the documentation of this file.
1 /*
2  * 'OpenSSL for Ruby' project
3  * Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net>
4  * All rights reserved.
5  */
6 /*
7  * This program is licensed under the same licence as Ruby.
8  * (See the file 'LICENCE'.)
9  */
10 /* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
11 #include "ossl.h"
12 
13 #define NewBN(klass) \
14  TypedData_Wrap_Struct((klass), &ossl_bn_type, 0)
15 #define SetBN(obj, bn) do { \
16  if (!(bn)) { \
17  ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
18  } \
19  RTYPEDDATA_DATA(obj) = (bn); \
20 } while (0)
21 
22 #define GetBN(obj, bn) do { \
23  TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \
24  if (!(bn)) { \
25  ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
26  } \
27 } while (0)
28 
29 #define SafeGetBN(obj, bn) do { \
30  OSSL_Check_Kind((obj), cBN); \
31  GetBN((obj), (bn)); \
32 } while (0)
33 
34 static void
35 ossl_bn_free(void *ptr)
36 {
37  BN_clear_free(ptr);
38 }
39 
40 static const rb_data_type_t ossl_bn_type = {
41  "OpenSSL/BN",
42  {
43  0, ossl_bn_free,
44  },
46 };
47 
48 /*
49  * Classes
50  */
52 
53 /* Document-class: OpenSSL::BNError
54  *
55  * Generic Error for all of OpenSSL::BN (big num)
56  */
58 
59 /*
60  * Public
61  */
62 VALUE
63 ossl_bn_new(const BIGNUM *bn)
64 {
65  BIGNUM *newbn;
66  VALUE obj;
67 
68  obj = NewBN(cBN);
69  newbn = bn ? BN_dup(bn) : BN_new();
70  if (!newbn) {
72  }
73  SetBN(obj, newbn);
74 
75  return obj;
76 }
77 
78 static BIGNUM *
79 integer_to_bnptr(VALUE obj, BIGNUM *orig)
80 {
81  BIGNUM *bn;
82 
83  if (FIXNUM_P(obj)) {
84  long i;
85  unsigned char bin[sizeof(long)];
86  long n = FIX2LONG(obj);
87  unsigned long un = labs(n);
88 
89  for (i = sizeof(long) - 1; 0 <= i; i--) {
90  bin[i] = un & 0xff;
91  un >>= 8;
92  }
93 
94  bn = BN_bin2bn(bin, sizeof(bin), orig);
95  if (!bn)
96  ossl_raise(eBNError, "BN_bin2bn");
97  if (n < 0)
98  BN_set_negative(bn, 1);
99  }
100  else { /* assuming Bignum */
101  size_t len = rb_absint_size(obj, NULL);
102  unsigned char *bin;
103  VALUE buf;
104  int sign;
105 
106  if (INT_MAX < len) {
107  rb_raise(eBNError, "bignum too long");
108  }
109  bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
110  sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
111 
112  bn = BN_bin2bn(bin, (int)len, orig);
113  ALLOCV_END(buf);
114  if (!bn)
115  ossl_raise(eBNError, "BN_bin2bn");
116  if (sign < 0)
117  BN_set_negative(bn, 1);
118  }
119 
120  return bn;
121 }
122 
123 static VALUE
125 {
126  BIGNUM *bn;
127  VALUE newobj = Qnil;
128 
129  if (rb_obj_is_kind_of(obj, cBN))
130  return obj;
131  if (RB_INTEGER_TYPE_P(obj)) {
132  newobj = NewBN(cBN); /* Handle potential mem leaks */
133  bn = integer_to_bnptr(obj, NULL);
134  SetBN(newobj, bn);
135  }
136 
137  return newobj;
138 }
139 
140 BIGNUM *
141 ossl_bn_value_ptr(volatile VALUE *ptr)
142 {
143  VALUE tmp;
144  BIGNUM *bn;
145 
146  tmp = try_convert_to_bn(*ptr);
147  if (NIL_P(tmp))
148  ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
149  GetBN(tmp, bn);
150  *ptr = tmp;
151 
152  return bn;
153 }
154 
155 /*
156  * Private
157  */
158 /*
159  * BN_CTX - is used in more difficult math. ops
160  * (Why just 1? Because Ruby itself isn't thread safe,
161  * we don't need to care about threads)
162  */
163 BN_CTX *ossl_bn_ctx;
164 
165 static VALUE
167 {
168  BIGNUM *bn;
169  VALUE obj = NewBN(klass);
170 
171  if (!(bn = BN_new())) {
173  }
174  SetBN(obj, bn);
175 
176  return obj;
177 }
178 
179 /* Document-method: OpenSSL::BN.new
180  *
181  * call-seq:
182  * OpenSSL::BN.new => aBN
183  * OpenSSL::BN.new(bn) => aBN
184  * OpenSSL::BN.new(integer) => aBN
185  * OpenSSL::BN.new(string) => aBN
186  * OpenSSL::BN.new(string, 0 | 2 | 10 | 16) => aBN
187  *
188  * Construct a new OpenSSL BigNum object.
189  */
190 static VALUE
192 {
193  BIGNUM *bn;
194  VALUE str, bs;
195  int base = 10;
196 
197  if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
198  base = NUM2INT(bs);
199  }
200 
201  if (RB_INTEGER_TYPE_P(str)) {
202  GetBN(self, bn);
203  integer_to_bnptr(str, bn);
204 
205  return self;
206  }
207 
208  if (RTEST(rb_obj_is_kind_of(str, cBN))) {
209  BIGNUM *other;
210 
211  GetBN(self, bn);
212  GetBN(str, other); /* Safe - we checked kind_of? above */
213  if (!BN_copy(bn, other)) {
215  }
216  return self;
217  }
218 
219  GetBN(self, bn);
220  switch (base) {
221  case 0:
222  if (!BN_mpi2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
224  }
225  break;
226  case 2:
227  if (!BN_bin2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
229  }
230  break;
231  case 10:
232  if (!BN_dec2bn(&bn, StringValueCStr(str))) {
234  }
235  break;
236  case 16:
237  if (!BN_hex2bn(&bn, StringValueCStr(str))) {
239  }
240  break;
241  default:
242  ossl_raise(rb_eArgError, "invalid radix %d", base);
243  }
244  return self;
245 }
246 
247 /*
248  * call-seq:
249  * bn.to_s => string
250  * bn.to_s(base) => string
251  *
252  * === Parameters
253  * * +base+ - integer
254  * Valid values:
255  * * 0 - MPI
256  * * 2 - binary
257  * * 10 - the default
258  * * 16 - hex
259  */
260 static VALUE
262 {
263  BIGNUM *bn;
264  VALUE str, bs;
265  int base = 10, len;
266  char *buf;
267 
268  if (rb_scan_args(argc, argv, "01", &bs) == 1) {
269  base = NUM2INT(bs);
270  }
271  GetBN(self, bn);
272  switch (base) {
273  case 0:
274  len = BN_bn2mpi(bn, NULL);
275  str = rb_str_new(0, len);
276  if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len)
278  break;
279  case 2:
280  len = BN_num_bytes(bn);
281  str = rb_str_new(0, len);
282  if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len)
284  break;
285  case 10:
286  if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL);
287  str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
288  break;
289  case 16:
290  if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL);
291  str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
292  break;
293  default:
294  ossl_raise(rb_eArgError, "invalid radix %d", base);
295  }
296 
297  return str;
298 }
299 
300 /*
301  * call-seq:
302  * bn.to_i => integer
303  */
304 static VALUE
306 {
307  BIGNUM *bn;
308  char *txt;
309  VALUE num;
310 
311  GetBN(self, bn);
312 
313  if (!(txt = BN_bn2hex(bn))) {
315  }
316  num = rb_cstr_to_inum(txt, 16, Qtrue);
317  OPENSSL_free(txt);
318 
319  return num;
320 }
321 
322 static VALUE
324 {
325  return self;
326 }
327 
328 static VALUE
330 {
331  switch(TYPE(other)) {
332  case T_STRING:
333  self = ossl_bn_to_s(0, NULL, self);
334  break;
335  case T_FIXNUM:
336  case T_BIGNUM:
337  self = ossl_bn_to_i(self);
338  break;
339  default:
340  if (!RTEST(rb_obj_is_kind_of(other, cBN))) {
341  ossl_raise(rb_eTypeError, "Don't know how to coerce");
342  }
343  }
344  return rb_assoc_new(other, self);
345 }
346 
347 #define BIGNUM_BOOL1(func) \
348  static VALUE \
349  ossl_bn_##func(VALUE self) \
350  { \
351  BIGNUM *bn; \
352  GetBN(self, bn); \
353  if (BN_##func(bn)) { \
354  return Qtrue; \
355  } \
356  return Qfalse; \
357  }
358 
359 /*
360  * Document-method: OpenSSL::BN#zero?
361  * call-seq:
362  * bn.zero? => true | false
363  */
365 
366 /*
367  * Document-method: OpenSSL::BN#one?
368  * call-seq:
369  * bn.one? => true | false
370  */
372 
373 /*
374  * Document-method: OpenSSL::BN#odd?
375  * call-seq:
376  * bn.odd? => true | false
377  */
378 BIGNUM_BOOL1(is_odd)
379 
380 #define BIGNUM_1c(func) \
381  static VALUE \
382  ossl_bn_##func(VALUE self) \
383  { \
384  BIGNUM *bn, *result; \
385  VALUE obj; \
386  GetBN(self, bn); \
387  obj = NewBN(rb_obj_class(self)); \
388  if (!(result = BN_new())) { \
389  ossl_raise(eBNError, NULL); \
390  } \
391  if (!BN_##func(result, bn, ossl_bn_ctx)) { \
392  BN_free(result); \
393  ossl_raise(eBNError, NULL); \
394  } \
395  SetBN(obj, result); \
396  return obj; \
397  }
398 
399 /*
400  * Document-method: OpenSSL::BN#sqr
401  * call-seq:
402  * bn.sqr => aBN
403  */
405 
406 #define BIGNUM_2(func) \
407  static VALUE \
408  ossl_bn_##func(VALUE self, VALUE other) \
409  { \
410  BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
411  VALUE obj; \
412  GetBN(self, bn1); \
413  obj = NewBN(rb_obj_class(self)); \
414  if (!(result = BN_new())) { \
415  ossl_raise(eBNError, NULL); \
416  } \
417  if (!BN_##func(result, bn1, bn2)) { \
418  BN_free(result); \
419  ossl_raise(eBNError, NULL); \
420  } \
421  SetBN(obj, result); \
422  return obj; \
423  }
424 
425 /*
426  * Document-method: OpenSSL::BN#+
427  * call-seq:
428  * bn + bn2 => aBN
429  */
430 BIGNUM_2(add)
431 
432 /*
433  * Document-method: OpenSSL::BN#-
434  * call-seq:
435  * bn - bn2 => aBN
436  */
437 BIGNUM_2(sub)
438 
439 #define BIGNUM_2c(func) \
440  static VALUE \
441  ossl_bn_##func(VALUE self, VALUE other) \
442  { \
443  BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
444  VALUE obj; \
445  GetBN(self, bn1); \
446  obj = NewBN(rb_obj_class(self)); \
447  if (!(result = BN_new())) { \
448  ossl_raise(eBNError, NULL); \
449  } \
450  if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \
451  BN_free(result); \
452  ossl_raise(eBNError, NULL); \
453  } \
454  SetBN(obj, result); \
455  return obj; \
456  }
457 
458 /*
459  * Document-method: OpenSSL::BN#*
460  * call-seq:
461  * bn * bn2 => aBN
462  */
463 BIGNUM_2c(mul)
464 
465 /*
466  * Document-method: OpenSSL::BN#%
467  * call-seq:
468  * bn % bn2 => aBN
469  */
470 BIGNUM_2c(mod)
471 
472 /*
473  * Document-method: OpenSSL::BN#**
474  * call-seq:
475  * bn ** bn2 => aBN
476  */
477 BIGNUM_2c(exp)
478 
479 /*
480  * Document-method: OpenSSL::BN#gcd
481  * call-seq:
482  * bn.gcd(bn2) => aBN
483  */
484 BIGNUM_2c(gcd)
485 
486 /*
487  * Document-method: OpenSSL::BN#mod_sqr
488  * call-seq:
489  * bn.mod_sqr(bn2) => aBN
490  */
491 BIGNUM_2c(mod_sqr)
492 
493 /*
494  * Document-method: OpenSSL::BN#mod_inverse
495  * call-seq:
496  * bn.mod_inverse(bn2) => aBN
497  */
498 BIGNUM_2c(mod_inverse)
499 
500 /*
501  * Document-method: OpenSSL::BN#/
502  * call-seq:
503  * bn1 / bn2 => [result, remainder]
504  *
505  * Division of OpenSSL::BN instances
506  */
507 static VALUE
508 ossl_bn_div(VALUE self, VALUE other)
509 {
510  BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2;
511  VALUE klass, obj1, obj2;
512 
513  GetBN(self, bn1);
514 
515  klass = rb_obj_class(self);
516  obj1 = NewBN(klass);
517  obj2 = NewBN(klass);
518  if (!(r1 = BN_new())) {
520  }
521  if (!(r2 = BN_new())) {
522  BN_free(r1);
524  }
525  if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) {
526  BN_free(r1);
527  BN_free(r2);
529  }
530  SetBN(obj1, r1);
531  SetBN(obj2, r2);
532 
533  return rb_ary_new3(2, obj1, obj2);
534 }
535 
536 #define BIGNUM_3c(func) \
537  static VALUE \
538  ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
539  { \
540  BIGNUM *bn1, *bn2 = GetBNPtr(other1); \
541  BIGNUM *bn3 = GetBNPtr(other2), *result; \
542  VALUE obj; \
543  GetBN(self, bn1); \
544  obj = NewBN(rb_obj_class(self)); \
545  if (!(result = BN_new())) { \
546  ossl_raise(eBNError, NULL); \
547  } \
548  if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \
549  BN_free(result); \
550  ossl_raise(eBNError, NULL); \
551  } \
552  SetBN(obj, result); \
553  return obj; \
554  }
555 
556 /*
557  * Document-method: OpenSSL::BN#mod_add
558  * call-seq:
559  * bn.mod_add(bn1, bn2) -> aBN
560  */
561 BIGNUM_3c(mod_add)
562 
563 /*
564  * Document-method: OpenSSL::BN#mod_sub
565  * call-seq:
566  * bn.mod_sub(bn1, bn2) -> aBN
567  */
568 BIGNUM_3c(mod_sub)
569 
570 /*
571  * Document-method: OpenSSL::BN#mod_mul
572  * call-seq:
573  * bn.mod_mul(bn1, bn2) -> aBN
574  */
575 BIGNUM_3c(mod_mul)
576 
577 /*
578  * Document-method: OpenSSL::BN#mod_exp
579  * call-seq:
580  * bn.mod_exp(bn1, bn2) -> aBN
581  */
582 BIGNUM_3c(mod_exp)
583 
584 #define BIGNUM_BIT(func) \
585  static VALUE \
586  ossl_bn_##func(VALUE self, VALUE bit) \
587  { \
588  BIGNUM *bn; \
589  GetBN(self, bn); \
590  if (!BN_##func(bn, NUM2INT(bit))) { \
591  ossl_raise(eBNError, NULL); \
592  } \
593  return self; \
594  }
595 
596 /*
597  * Document-method: OpenSSL::BN#set_bit!
598  * call-seq:
599  * bn.set_bit!(bit) -> self
600  */
601 BIGNUM_BIT(set_bit)
602 
603 /*
604  * Document-method: OpenSSL::BN#clear_bit!
605  * call-seq:
606  * bn.clear_bit!(bit) -> self
607  */
608 BIGNUM_BIT(clear_bit)
609 
610 /*
611  * Document-method: OpenSSL::BN#mask_bit!
612  * call-seq:
613  * bn.mask_bit!(bit) -> self
614  */
615 BIGNUM_BIT(mask_bits)
616 
617 /* Document-method: OpenSSL::BN#bit_set?
618  * call-seq:
619  * bn.bit_set?(bit) => true | false
620  *
621  * Returns boolean of whether +bit+ is set.
622  * Bitwise operations for openssl BIGNUMs.
623  */
624 static VALUE
625 ossl_bn_is_bit_set(VALUE self, VALUE bit)
626 {
627  int b;
628  BIGNUM *bn;
629 
630  b = NUM2INT(bit);
631  GetBN(self, bn);
632  if (BN_is_bit_set(bn, b)) {
633  return Qtrue;
634  }
635  return Qfalse;
636 }
637 
638 #define BIGNUM_SHIFT(func) \
639  static VALUE \
640  ossl_bn_##func(VALUE self, VALUE bits) \
641  { \
642  BIGNUM *bn, *result; \
643  int b; \
644  VALUE obj; \
645  b = NUM2INT(bits); \
646  GetBN(self, bn); \
647  obj = NewBN(rb_obj_class(self)); \
648  if (!(result = BN_new())) { \
649  ossl_raise(eBNError, NULL); \
650  } \
651  if (!BN_##func(result, bn, b)) { \
652  BN_free(result); \
653  ossl_raise(eBNError, NULL); \
654  } \
655  SetBN(obj, result); \
656  return obj; \
657  }
658 
659 /*
660  * Document-method: OpenSSL::BN#<<
661  * call-seq:
662  * bn << bits -> aBN
663  */
665 
666 /*
667  * Document-method: OpenSSL::BN#>>
668  * call-seq:
669  * bn >> bits -> aBN
670  */
671 BIGNUM_SHIFT(rshift)
672 
673 #define BIGNUM_SELF_SHIFT(func) \
674  static VALUE \
675  ossl_bn_self_##func(VALUE self, VALUE bits) \
676  { \
677  BIGNUM *bn; \
678  int b; \
679  b = NUM2INT(bits); \
680  GetBN(self, bn); \
681  if (!BN_##func(bn, bn, b)) \
682  ossl_raise(eBNError, NULL); \
683  return self; \
684  }
685 
686 /*
687  * Document-method: OpenSSL::BN#lshift!
688  * call-seq:
689  * bn.lshift!(bits) -> self
690  */
692 
693 /*
694  * Document-method: OpenSSL::BN#rshift!
695  * call-seq:
696  * bn.rshift!(bits) -> self
697  */
698 BIGNUM_SELF_SHIFT(rshift)
699 
700 #define BIGNUM_RAND(func) \
701  static VALUE \
702  ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
703  { \
704  BIGNUM *result; \
705  int bottom = 0, top = 0, b; \
706  VALUE bits, fill, odd, obj; \
707  \
708  switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \
709  case 3: \
710  bottom = (odd == Qtrue) ? 1 : 0; \
711  /* FALLTHROUGH */ \
712  case 2: \
713  top = NUM2INT(fill); \
714  } \
715  b = NUM2INT(bits); \
716  obj = NewBN(klass); \
717  if (!(result = BN_new())) { \
718  ossl_raise(eBNError, NULL); \
719  } \
720  if (!BN_##func(result, b, top, bottom)) { \
721  BN_free(result); \
722  ossl_raise(eBNError, NULL); \
723  } \
724  SetBN(obj, result); \
725  return obj; \
726  }
727 
728 /*
729  * Document-method: OpenSSL::BN.rand
730  * BN.rand(bits [, fill [, odd]]) -> aBN
731  */
732 BIGNUM_RAND(rand)
733 
734 /*
735  * Document-method: OpenSSL::BN.pseudo_rand
736  * BN.pseudo_rand(bits [, fill [, odd]]) -> aBN
737  */
738 BIGNUM_RAND(pseudo_rand)
739 
740 #define BIGNUM_RAND_RANGE(func) \
741  static VALUE \
742  ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
743  { \
744  BIGNUM *bn = GetBNPtr(range), *result; \
745  VALUE obj = NewBN(klass); \
746  if (!(result = BN_new())) { \
747  ossl_raise(eBNError, NULL); \
748  } \
749  if (!BN_##func##_range(result, bn)) { \
750  BN_free(result); \
751  ossl_raise(eBNError, NULL); \
752  } \
753  SetBN(obj, result); \
754  return obj; \
755  }
756 
757 /*
758  * Document-method: OpenSSL::BN.rand_range
759  * call-seq:
760  * BN.rand_range(range) -> aBN
761  *
762  */
763 BIGNUM_RAND_RANGE(rand)
764 
765 /*
766  * Document-method: OpenSSL::BN.pseudo_rand_range
767  * call-seq:
768  * BN.pseudo_rand_range(range) -> aBN
769  *
770  */
771 BIGNUM_RAND_RANGE(pseudo_rand)
772 
773 /*
774  * call-seq:
775  * BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn
776  *
777  * Generates a random prime number of bit length +bits+. If +safe+ is true,
778  * generates a safe prime. If +add+ is specified, generates a prime that
779  * fulfills condition <tt>p % add = rem</tt>.
780  *
781  * === Parameters
782  * * +bits+ - integer
783  * * +safe+ - boolean
784  * * +add+ - BN
785  * * +rem+ - BN
786  */
787 static VALUE
789 {
790  BIGNUM *add = NULL, *rem = NULL, *result;
791  int safe = 1, num;
792  VALUE vnum, vsafe, vadd, vrem, obj;
793 
794  rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem);
795 
796  num = NUM2INT(vnum);
797 
798  if (vsafe == Qfalse) {
799  safe = 0;
800  }
801  if (!NIL_P(vadd)) {
802  add = GetBNPtr(vadd);
803  rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
804  }
805  obj = NewBN(klass);
806  if (!(result = BN_new())) {
808  }
809  if (!BN_generate_prime_ex(result, num, safe, add, rem, NULL)) {
810  BN_free(result);
812  }
813  SetBN(obj, result);
814 
815  return obj;
816 }
817 
818 #define BIGNUM_NUM(func) \
819  static VALUE \
820  ossl_bn_##func(VALUE self) \
821  { \
822  BIGNUM *bn; \
823  GetBN(self, bn); \
824  return INT2NUM(BN_##func(bn)); \
825  }
826 
827 /*
828  * Document-method: OpenSSL::BN#num_bytes
829  * call-seq:
830  * bn.num_bytes => integer
831  */
832 BIGNUM_NUM(num_bytes)
833 
834 /*
835  * Document-method: OpenSSL::BN#num_bits
836  * call-seq:
837  * bn.num_bits => integer
838  */
839 BIGNUM_NUM(num_bits)
840 
841 static VALUE
843 {
844  BIGNUM *bn1, *bn2;
845 
846  rb_check_frozen(self);
847 
848  if (self == other) return self;
849 
850  GetBN(self, bn1);
851  bn2 = GetBNPtr(other);
852 
853  if (!BN_copy(bn1, bn2)) {
855  }
856  return self;
857 }
858 
859 #define BIGNUM_CMP(func) \
860  static VALUE \
861  ossl_bn_##func(VALUE self, VALUE other) \
862  { \
863  BIGNUM *bn1, *bn2 = GetBNPtr(other); \
864  GetBN(self, bn1); \
865  return INT2NUM(BN_##func(bn1, bn2)); \
866  }
867 
868 /*
869  * Document-method: OpenSSL::BN#cmp
870  * call-seq:
871  * bn.cmp(bn2) => integer
872  */
873 /*
874  * Document-method: OpenSSL::BN#<=>
875  * call-seq:
876  * bn <=> bn2 => integer
877  */
879 
880 /*
881  * Document-method: OpenSSL::BN#ucmp
882  * call-seq:
883  * bn.ucmp(bn2) => integer
884  */
885 BIGNUM_CMP(ucmp)
886 
887 /*
888  * call-seq:
889  * bn == obj => true or false
890  *
891  * Returns +true+ only if +obj+ has the same value as +bn+. Contrast this
892  * with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN.
893  */
894 static VALUE
895 ossl_bn_eq(VALUE self, VALUE other)
896 {
897  BIGNUM *bn1, *bn2;
898 
899  GetBN(self, bn1);
900  other = try_convert_to_bn(other);
901  if (NIL_P(other))
902  return Qfalse;
903  GetBN(other, bn2);
904 
905  if (!BN_cmp(bn1, bn2)) {
906  return Qtrue;
907  }
908  return Qfalse;
909 }
910 
911 /*
912  * call-seq:
913  * bn.eql?(obj) => true or false
914  *
915  * Returns <code>true</code> only if <i>obj</i> is a
916  * <code>OpenSSL::BN</code> with the same value as <i>big</i>. Contrast this
917  * with OpenSSL::BN#==, which performs type conversions.
918  */
919 static VALUE
920 ossl_bn_eql(VALUE self, VALUE other)
921 {
922  BIGNUM *bn1, *bn2;
923 
924  if (!rb_obj_is_kind_of(other, cBN))
925  return Qfalse;
926  GetBN(self, bn1);
927  GetBN(other, bn2);
928 
929  return BN_cmp(bn1, bn2) ? Qfalse : Qtrue;
930 }
931 
932 /*
933  * call-seq:
934  * bn.hash => Integer
935  *
936  * Returns a hash code for this object.
937  *
938  * See also Object#hash.
939  */
940 static VALUE
942 {
943  BIGNUM *bn;
944  VALUE hash;
945  unsigned char *buf;
946  int len;
947 
948  GetBN(self, bn);
949  len = BN_num_bytes(bn);
950  buf = xmalloc(len);
951  if (BN_bn2bin(bn, buf) != len) {
952  xfree(buf);
954  }
955 
956  hash = ST2FIX(rb_memhash(buf, len));
957  xfree(buf);
958 
959  return hash;
960 }
961 
962 /*
963  * call-seq:
964  * bn.prime? => true | false
965  * bn.prime?(checks) => true | false
966  *
967  * Performs a Miller-Rabin probabilistic primality test with +checks+
968  * iterations. If +nchecks+ is not specified, a number of iterations is used
969  * that yields a false positive rate of at most 2^-80 for random input.
970  *
971  * === Parameters
972  * * +checks+ - integer
973  */
974 static VALUE
976 {
977  BIGNUM *bn;
978  VALUE vchecks;
979  int checks = BN_prime_checks;
980 
981  if (rb_scan_args(argc, argv, "01", &vchecks) == 1) {
982  checks = NUM2INT(vchecks);
983  }
984  GetBN(self, bn);
985  switch (BN_is_prime_ex(bn, checks, ossl_bn_ctx, NULL)) {
986  case 1:
987  return Qtrue;
988  case 0:
989  return Qfalse;
990  default:
992  }
993  /* not reachable */
994  return Qnil;
995 }
996 
997 /*
998  * call-seq:
999  * bn.prime_fasttest? => true | false
1000  * bn.prime_fasttest?(checks) => true | false
1001  * bn.prime_fasttest?(checks, trial_div) => true | false
1002  *
1003  * Performs a Miller-Rabin primality test. This is same as #prime? except this
1004  * first attempts trial divisions with some small primes.
1005  *
1006  * === Parameters
1007  * * +checks+ - integer
1008  * * +trial_div+ - boolean
1009  */
1010 static VALUE
1012 {
1013  BIGNUM *bn;
1014  VALUE vchecks, vtrivdiv;
1015  int checks = BN_prime_checks, do_trial_division = 1;
1016 
1017  rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv);
1018 
1019  if (!NIL_P(vchecks)) {
1020  checks = NUM2INT(vchecks);
1021  }
1022  GetBN(self, bn);
1023  /* handle true/false */
1024  if (vtrivdiv == Qfalse) {
1025  do_trial_division = 0;
1026  }
1027  switch (BN_is_prime_fasttest_ex(bn, checks, ossl_bn_ctx, do_trial_division, NULL)) {
1028  case 1:
1029  return Qtrue;
1030  case 0:
1031  return Qfalse;
1032  default:
1034  }
1035  /* not reachable */
1036  return Qnil;
1037 }
1038 
1039 /*
1040  * INIT
1041  * (NOTE: ordering of methods is the same as in 'man bn')
1042  */
1043 void
1045 {
1046 #if 0
1047  mOSSL = rb_define_module("OpenSSL");
1049 #endif
1050 
1051  if (!(ossl_bn_ctx = BN_CTX_new())) {
1052  ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
1053  }
1054 
1056 
1058 
1060  rb_define_method(cBN, "initialize", ossl_bn_initialize, -1);
1061 
1063  rb_define_method(cBN, "copy", ossl_bn_copy, 1);
1064 
1065  /* swap (=coerce?) */
1066 
1067  rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0);
1068  rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0);
1069  /* num_bits_word */
1070 
1071  rb_define_method(cBN, "+", ossl_bn_add, 1);
1072  rb_define_method(cBN, "-", ossl_bn_sub, 1);
1073  rb_define_method(cBN, "*", ossl_bn_mul, 1);
1074  rb_define_method(cBN, "sqr", ossl_bn_sqr, 0);
1075  rb_define_method(cBN, "/", ossl_bn_div, 1);
1076  rb_define_method(cBN, "%", ossl_bn_mod, 1);
1077  /* nnmod */
1078 
1079  rb_define_method(cBN, "mod_add", ossl_bn_mod_add, 2);
1080  rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2);
1081  rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2);
1082  rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1);
1083  rb_define_method(cBN, "**", ossl_bn_exp, 1);
1084  rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2);
1085  rb_define_method(cBN, "gcd", ossl_bn_gcd, 1);
1086 
1087  /* add_word
1088  * sub_word
1089  * mul_word
1090  * div_word
1091  * mod_word */
1092 
1093  rb_define_method(cBN, "cmp", ossl_bn_cmp, 1);
1094  rb_define_alias(cBN, "<=>", "cmp");
1095  rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1);
1096  rb_define_method(cBN, "eql?", ossl_bn_eql, 1);
1097  rb_define_method(cBN, "hash", ossl_bn_hash, 0);
1098  rb_define_method(cBN, "==", ossl_bn_eq, 1);
1099  rb_define_alias(cBN, "===", "==");
1100  rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0);
1101  rb_define_method(cBN, "one?", ossl_bn_is_one, 0);
1102  /* is_word */
1103  rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0);
1104 
1105  /* zero
1106  * one
1107  * value_one - DON'T IMPL.
1108  * set_word
1109  * get_word */
1110 
1111  rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1);
1112  rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1);
1113  rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1);
1114  rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1);
1115 
1117  rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1);
1118  rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1);
1119 
1120  rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1);
1121  rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1);
1122  rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1);
1123  rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1);
1124  rb_define_method(cBN, "<<", ossl_bn_lshift, 1);
1125  rb_define_method(cBN, ">>", ossl_bn_rshift, 1);
1126  rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1);
1127  rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1);
1128  /* lshift1 - DON'T IMPL. */
1129  /* rshift1 - DON'T IMPL. */
1130 
1131  /*
1132  * bn2bin
1133  * bin2bn
1134  * bn2hex
1135  * bn2dec
1136  * hex2bn
1137  * dec2bn - all these are implemented in ossl_bn_initialize, and ossl_bn_to_s
1138  * print - NOT IMPL.
1139  * print_fp - NOT IMPL.
1140  * bn2mpi
1141  * mpi2bn
1142  */
1143  rb_define_method(cBN, "to_s", ossl_bn_to_s, -1);
1144  rb_define_method(cBN, "to_i", ossl_bn_to_i, 0);
1145  rb_define_alias(cBN, "to_int", "to_i");
1146  rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0);
1147  rb_define_method(cBN, "coerce", ossl_bn_coerce, 1);
1148 
1149  /*
1150  * TODO:
1151  * But how to: from_bin, from_mpi? PACK?
1152  * to_bin
1153  * to_mpi
1154  */
1155 
1156  rb_define_method(cBN, "mod_inverse", ossl_bn_mod_inverse, 1);
1157 
1158  /* RECiProcal
1159  * MONTgomery */
1160 }
VALUE rb_eStandardError
Definition: error.c:760
static int cmp(VALUE x, VALUE y)
Definition: time.c:57
VALUE mOSSL
Definition: ossl.c:213
int rb_integer_pack(VALUE val, void *words, size_t numwords, size_t wordsize, size_t nails, int flags)
Definition: bignum.c:3531
static VALUE ossl_bn_hash(VALUE self)
Definition: ossl_bn.c:941
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1145
#define BIGNUM_RAND_RANGE(func)
Definition: ossl_bn.c:740
size_t strlen(const char *)
#define T_FIXNUM
Definition: ruby.h:503
static VALUE ossl_bn_alloc(VALUE klass)
Definition: ossl_bn.c:166
static int is_zero(VALUE x)
Definition: bigdecimal.c:2193
#define NUM2INT(x)
Definition: ruby.h:684
static unsigned int hash(str, len) register const char *str
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
#define r1
#define Qtrue
Definition: ruby.h:437
VALUE rb_eTypeError
Definition: error.c:762
static VALUE ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
Definition: ossl_bn.c:975
#define rb_long2int(n)
Definition: ruby.h:319
#define BIGNUM_RAND(func)
Definition: ossl_bn.c:700
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1502
static long labs(long const x)
Definition: bigdecimal.h:77
static VALUE ossl_bn_to_bn(VALUE self)
Definition: ossl_bn.c:323
#define GetBN(obj, bn)
Definition: ossl_bn.c:22
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
Definition: class.c:693
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2207
static const rb_data_type_t ossl_bn_type
Definition: ossl_bn.c:40
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:690
static int is_one(VALUE x)
Definition: bigdecimal.c:2216
#define FIXNUM_P(f)
Definition: ruby.h:365
static Bigint * lshift(Bigint *b, int k)
Definition: util.c:1424
static VALUE ossl_bn_eq(VALUE self, VALUE other)
Definition: ossl_bn.c:895
static VALUE ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
Definition: ossl_bn.c:1011
static BIGNUM * integer_to_bnptr(VALUE obj, BIGNUM *orig)
Definition: ossl_bn.c:79
#define BIGNUM_SHIFT(func)
Definition: ossl_bn.c:638
#define rb_define_copy_func(klass, func)
Definition: ruby_missing.h:13
#define BIGNUM_3c(func)
Definition: ossl_bn.c:536
#define BIGNUM_BOOL1(func)
Definition: ossl_bn.c:347
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1872
VALUE rb_eRuntimeError
Definition: error.c:761
#define GetBNPtr(obj)
Definition: ossl_bn.h:18
#define NIL_P(v)
Definition: ruby.h:451
#define add(x, y)
Definition: date_strftime.c:23
VALUE eOSSLError
Definition: ossl.c:218
#define TYPE(x)
Definition: ruby.h:521
int argc
Definition: ruby.c:183
#define BIGNUM_NUM(func)
Definition: ossl_bn.c:818
#define Qfalse
Definition: ruby.h:436
#define ALLOCV_N(type, v, n)
Definition: ruby.h:1657
#define T_BIGNUM
Definition: ruby.h:501
static VALUE ossl_bn_to_i(VALUE self)
Definition: ossl_bn.c:305
#define ALLOCV_END(v)
Definition: ruby.h:1658
#define BIGNUM_2(func)
static VALUE ossl_bn_eql(VALUE self, VALUE other)
Definition: ossl_bn.c:920
#define SetBN(obj, bn)
Definition: ossl_bn.c:15
#define NewBN(klass)
Definition: ossl_bn.c:13
#define sub(x, y)
Definition: date_strftime.c:24
void rb_define_alias(VALUE klass, const char *name1, const char *name2)
Defines an alias of a method.
Definition: class.c:1758
static VALUE ossl_bn_coerce(VALUE self, VALUE other)
Definition: ossl_bn.c:329
static VALUE ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
Definition: ossl_bn.c:191
#define BIGNUM_CMP(func)
Definition: ossl_bn.c:859
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1919
unsigned char buf[MIME_BUF_SIZE]
Definition: nkf.c:4309
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:623
#define Qnil
Definition: ruby.h:438
unsigned long VALUE
Definition: ruby.h:85
static VALUE result
Definition: nkf.c:40
static VALUE ossl_bn_copy(VALUE self, VALUE other)
Definition: ossl_bn.c:842
#define rb_ary_new3
Definition: intern.h:91
VALUE cBN
Definition: ossl_bn.c:51
size_t rb_absint_size(VALUE val, int *nlz_bits_ret)
Definition: bignum.c:3231
#define ST2FIX(h)
Definition: ruby.h:1579
char bin[32]
Definition: siphash.c:135
#define INTEGER_PACK_BIG_ENDIAN
Definition: intern.h:152
register unsigned int len
Definition: zonetab.h:51
#define StringValueCStr(v)
Definition: ruby.h:571
#define RSTRING_PTR(str)
Definition: ruby.h:982
#define mul(x, y)
Definition: date_strftime.c:25
#define xmalloc
Definition: defines.h:183
static VALUE try_convert_to_bn(VALUE obj)
Definition: ossl_bn.c:124
static void ossl_bn_free(void *ptr)
Definition: ossl_bn.c:35
BN_CTX * ossl_bn_ctx
Definition: ossl_bn.c:163
#define RTEST(v)
Definition: ruby.h:450
#define T_STRING
Definition: ruby.h:496
VALUE ossl_buf2str(char *buf, int len)
Definition: ossl.c:101
#define BIGNUM_BIT(func)
BIGNUM * ossl_bn_value_ptr(volatile VALUE *ptr)
Definition: ossl_bn.c:141
void ossl_raise(VALUE exc, const char *fmt,...)
Definition: ossl.c:278
void Init_ossl_bn(void)
Definition: ossl_bn.c:1044
VALUE ossl_bn_new(const BIGNUM *bn)
Definition: ossl_bn.c:63
#define BIGNUM_SELF_SHIFT(func)
Definition: ossl_bn.c:673
#define StringValuePtr(v)
Definition: ruby.h:570
#define RSTRING_LENINT(str)
Definition: ruby.h:990
#define rb_check_frozen(obj)
Definition: intern.h:276
#define r2
void void xfree(void *)
VALUE rb_define_module(const char *name)
Definition: class.c:768
VALUE rb_cstr_to_inum(const char *str, int base, int badcheck)
Definition: bignum.c:3994
#define BIGNUM_1c(func)
Definition: ossl_bn.c:380
#define mod(x, y)
Definition: date_strftime.c:28
#define RB_INTEGER_TYPE_P(obj)
Definition: ruby_missing.h:20
#define NULL
Definition: _sdbm.c:102
#define FIX2LONG(x)
Definition: ruby.h:363
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
static VALUE ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
Definition: ossl_bn.c:788
VALUE eBNError
Definition: ossl_bn.c:57
VALUE rb_eArgError
Definition: error.c:763
char ** argv
Definition: ruby.c:184
static VALUE ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
Definition: ossl_bn.c:261
VALUE rb_obj_class(VALUE)
Definition: object.c:229
VALUE rb_str_new(const char *, long)
Definition: string.c:736
#define BIGNUM_2c(func)