summaryrefslogtreecommitdiff
path: root/ext/openssl/ossl_bn.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/openssl/ossl_bn.c')
-rw-r--r--ext/openssl/ossl_bn.c224
1 files changed, 97 insertions, 127 deletions
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index 8d0f63a986..ce0d3ec7ee 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -41,7 +41,7 @@ static const rb_data_type_t ossl_bn_type = {
{
0, ossl_bn_free,
},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
};
/*
@@ -577,22 +577,33 @@ BIGNUM_2c(gcd)
*/
BIGNUM_2c(mod_sqr)
+#define BIGNUM_2cr(func) \
+ static VALUE \
+ ossl_bn_##func(VALUE self, VALUE other) \
+ { \
+ BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
+ VALUE obj; \
+ GetBN(self, bn1); \
+ obj = NewBN(rb_obj_class(self)); \
+ if (!(result = BN_##func(NULL, bn1, bn2, ossl_bn_ctx))) \
+ ossl_raise(eBNError, NULL); \
+ SetBN(obj, result); \
+ return obj; \
+ }
+
/*
+ * Document-method: OpenSSL::BN#mod_sqrt
+ * call-seq:
+ * bn.mod_sqrt(bn2) => aBN
+ */
+BIGNUM_2cr(mod_sqrt)
+
+/*
+ * Document-method: OpenSSL::BN#mod_inverse
* call-seq:
* bn.mod_inverse(bn2) => aBN
*/
-static VALUE
-ossl_bn_mod_inverse(VALUE self, VALUE other)
-{
- BIGNUM *bn1, *bn2 = GetBNPtr(other), *result;
- VALUE obj;
- GetBN(self, bn1);
- obj = NewBN(rb_obj_class(self));
- if (!(result = BN_mod_inverse(NULL, bn1, bn2, ossl_bn_ctx)))
- ossl_raise(eBNError, "BN_mod_inverse");
- SetBN(obj, result);
- return obj;
-}
+BIGNUM_2cr(mod_inverse)
/*
* call-seq:
@@ -792,78 +803,64 @@ BIGNUM_SELF_SHIFT(lshift)
*/
BIGNUM_SELF_SHIFT(rshift)
-#define BIGNUM_RAND(func) \
- static VALUE \
- ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
- { \
- BIGNUM *result; \
- int bottom = 0, top = 0, b; \
- VALUE bits, fill, odd, obj; \
- \
- switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \
- case 3: \
- bottom = (odd == Qtrue) ? 1 : 0; \
- /* FALLTHROUGH */ \
- case 2: \
- top = NUM2INT(fill); \
- } \
- b = NUM2INT(bits); \
- obj = NewBN(klass); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func(result, b, top, bottom) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
- }
-
-/*
- * Document-method: OpenSSL::BN.rand
- * BN.rand(bits [, fill [, odd]]) -> aBN
- */
-BIGNUM_RAND(rand)
-
-/*
- * Document-method: OpenSSL::BN.pseudo_rand
- * BN.pseudo_rand(bits [, fill [, odd]]) -> aBN
- */
-BIGNUM_RAND(pseudo_rand)
-
-#define BIGNUM_RAND_RANGE(func) \
- static VALUE \
- ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
- { \
- BIGNUM *bn = GetBNPtr(range), *result; \
- VALUE obj = NewBN(klass); \
- if (!(result = BN_new())) { \
- ossl_raise(eBNError, NULL); \
- } \
- if (BN_##func##_range(result, bn) <= 0) { \
- BN_free(result); \
- ossl_raise(eBNError, NULL); \
- } \
- SetBN(obj, result); \
- return obj; \
- }
-
/*
- * Document-method: OpenSSL::BN.rand_range
* call-seq:
- * BN.rand_range(range) -> aBN
+ * BN.rand(bits [, fill [, odd]]) -> aBN
*
+ * Generates a cryptographically strong pseudo-random number of +bits+.
+ *
+ * See also the man page BN_rand(3).
*/
-BIGNUM_RAND_RANGE(rand)
+static VALUE
+ossl_bn_s_rand(int argc, VALUE *argv, VALUE klass)
+{
+ BIGNUM *result;
+ int bottom = 0, top = 0, b;
+ VALUE bits, fill, odd, obj;
+
+ switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) {
+ case 3:
+ bottom = (odd == Qtrue) ? 1 : 0;
+ /* FALLTHROUGH */
+ case 2:
+ top = NUM2INT(fill);
+ }
+ b = NUM2INT(bits);
+ obj = NewBN(klass);
+ if (!(result = BN_new())) {
+ ossl_raise(eBNError, "BN_new");
+ }
+ if (BN_rand(result, b, top, bottom) <= 0) {
+ BN_free(result);
+ ossl_raise(eBNError, "BN_rand");
+ }
+ SetBN(obj, result);
+ return obj;
+}
/*
- * Document-method: OpenSSL::BN.pseudo_rand_range
* call-seq:
- * BN.pseudo_rand_range(range) -> aBN
+ * BN.rand_range(range) -> aBN
+ *
+ * Generates a cryptographically strong pseudo-random number in the range
+ * 0...+range+.
*
+ * See also the man page BN_rand_range(3).
*/
-BIGNUM_RAND_RANGE(pseudo_rand)
+static VALUE
+ossl_bn_s_rand_range(VALUE klass, VALUE range)
+{
+ BIGNUM *bn = GetBNPtr(range), *result;
+ VALUE obj = NewBN(klass);
+ if (!(result = BN_new()))
+ ossl_raise(eBNError, "BN_new");
+ if (BN_rand_range(result, bn) <= 0) {
+ BN_free(result);
+ ossl_raise(eBNError, "BN_rand_range");
+ }
+ SetBN(obj, result);
+ return obj;
+}
/*
* call-seq:
@@ -1118,34 +1115,29 @@ ossl_bn_hash(VALUE self)
* bn.prime? => true | false
* bn.prime?(checks) => true | false
*
- * Performs a Miller-Rabin probabilistic primality test with _checks_
- * iterations. If _checks_ is not specified, a number of iterations is used
- * that yields a false positive rate of at most 2^-80 for random input.
+ * Performs a Miller-Rabin probabilistic primality test for +bn+.
*
- * === Parameters
- * * _checks_ - integer
+ * <b>+checks+ parameter is deprecated in version 3.0.</b> It has no effect.
*/
static VALUE
ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
{
BIGNUM *bn;
- VALUE vchecks;
- int checks = BN_prime_checks;
+ int ret;
- if (rb_scan_args(argc, argv, "01", &vchecks) == 1) {
- checks = NUM2INT(vchecks);
- }
+ rb_check_arity(argc, 0, 1);
GetBN(self, bn);
- switch (BN_is_prime_ex(bn, checks, ossl_bn_ctx, NULL)) {
- case 1:
- return Qtrue;
- case 0:
- return Qfalse;
- default:
- ossl_raise(eBNError, NULL);
- }
- /* not reachable */
- return Qnil;
+
+#ifdef HAVE_BN_CHECK_PRIME
+ ret = BN_check_prime(bn, ossl_bn_ctx, NULL);
+ if (ret < 0)
+ ossl_raise(eBNError, "BN_check_prime");
+#else
+ ret = BN_is_prime_fasttest_ex(bn, BN_prime_checks, ossl_bn_ctx, 1, NULL);
+ if (ret < 0)
+ ossl_raise(eBNError, "BN_is_prime_fasttest_ex");
+#endif
+ return ret ? Qtrue : Qfalse;
}
/*
@@ -1154,40 +1146,17 @@ ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
* bn.prime_fasttest?(checks) => true | false
* bn.prime_fasttest?(checks, trial_div) => true | false
*
- * Performs a Miller-Rabin primality test. This is same as #prime? except this
- * first attempts trial divisions with some small primes.
+ * Performs a Miller-Rabin probabilistic primality test for +bn+.
*
- * === Parameters
- * * _checks_ - integer
- * * _trial_div_ - boolean
+ * <b>Deprecated in version 3.0.</b> Use #prime? instead.
+ *
+ * +checks+ and +trial_div+ parameters no longer have any effect.
*/
static VALUE
ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
{
- BIGNUM *bn;
- VALUE vchecks, vtrivdiv;
- int checks = BN_prime_checks, do_trial_division = 1;
-
- rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv);
-
- if (!NIL_P(vchecks)) {
- checks = NUM2INT(vchecks);
- }
- GetBN(self, bn);
- /* handle true/false */
- if (vtrivdiv == Qfalse) {
- do_trial_division = 0;
- }
- switch (BN_is_prime_fasttest_ex(bn, checks, ossl_bn_ctx, do_trial_division, NULL)) {
- case 1:
- return Qtrue;
- case 0:
- return Qfalse;
- default:
- ossl_raise(eBNError, NULL);
- }
- /* not reachable */
- return Qnil;
+ rb_check_arity(argc, 0, 2);
+ return ossl_bn_is_prime(0, argv, self);
}
/*
@@ -1276,6 +1245,7 @@ Init_ossl_bn(void)
rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2);
rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2);
rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1);
+ rb_define_method(cBN, "mod_sqrt", ossl_bn_mod_sqrt, 1);
rb_define_method(cBN, "**", ossl_bn_exp, 1);
rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2);
rb_define_method(cBN, "gcd", ossl_bn_gcd, 1);
@@ -1306,9 +1276,9 @@ Init_ossl_bn(void)
* get_word */
rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1);
- rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1);
rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1);
- rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1);
+ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand", "rand");
+ rb_define_alias(rb_singleton_class(cBN), "pseudo_rand_range", "rand_range");
rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1);
rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1);