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