summaryrefslogtreecommitdiffstats
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.c165
1 files changed, 101 insertions, 64 deletions
diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c
index 6a0a21e..19a868c 100644
--- a/ext/openssl/ossl_bn.c
+++ b/ext/openssl/ossl_bn.c
@@ -52,8 +52,6 @@ VALUE cBN;
/* Document-class: OpenSSL::BNError
*
- * BNError < OpenSSLError
- *
* Generic Error for all of OpenSSL::BN (big num)
*/
VALUE eBNError;
@@ -78,24 +76,65 @@ ossl_bn_new(const BIGNUM *bn)
}
static BIGNUM *
+integer_to_bnptr(VALUE obj, BIGNUM *orig)
+{
+ BIGNUM *bn;
+
+ if (FIXNUM_P(obj)) {
+ long i;
+ unsigned char bin[sizeof(long)];
+ long n = FIX2LONG(obj);
+ unsigned long un = labs(n);
+
+ for (i = sizeof(long) - 1; 0 <= i; i--) {
+ bin[i] = un & 0xff;
+ un >>= 8;
+ }
+
+ bn = BN_bin2bn(bin, sizeof(bin), orig);
+ if (!bn)
+ ossl_raise(eBNError, "BN_bin2bn");
+ if (n < 0)
+ BN_set_negative(bn, 1);
+ }
+ else { /* assuming Bignum */
+ size_t len = rb_absint_size(obj, NULL);
+ unsigned char *bin;
+ VALUE buf;
+ int sign;
+
+ if (INT_MAX < len) {
+ rb_raise(eBNError, "bignum too long");
+ }
+ bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
+ sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
+
+ bn = BN_bin2bn(bin, (int)len, orig);
+ ALLOCV_END(buf);
+ if (!bn)
+ ossl_raise(eBNError, "BN_bin2bn");
+ if (sign < 0)
+ BN_set_negative(bn, 1);
+ }
+
+ return bn;
+}
+
+static BIGNUM *
try_convert_to_bnptr(VALUE obj)
{
BIGNUM *bn = NULL;
VALUE newobj;
- if (RTEST(rb_obj_is_kind_of(obj, cBN))) {
+ if (rb_obj_is_kind_of(obj, cBN)) {
GetBN(obj, bn);
- } else switch (TYPE(obj)) {
- case T_FIXNUM:
- case T_BIGNUM:
- obj = rb_String(obj);
- newobj = NewBN(cBN); /* GC bug */
- if (!BN_dec2bn(&bn, StringValueCStr(obj))) {
- ossl_raise(eBNError, NULL);
- }
- SetBN(newobj, bn); /* Handle potencial mem leaks */
- break;
}
+ else if (RB_INTEGER_TYPE_P(obj)) {
+ newobj = NewBN(cBN); /* Handle potencial mem leaks */
+ bn = integer_to_bnptr(obj, NULL);
+ SetBN(newobj, bn);
+ }
+
return bn;
}
@@ -135,6 +174,7 @@ ossl_bn_alloc(VALUE klass)
/* Document-method: OpenSSL::BN.new
*
+ * call-seq:
* OpenSSL::BN.new => aBN
* OpenSSL::BN.new(bn) => aBN
* OpenSSL::BN.new(integer) => aBN
@@ -154,45 +194,13 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
base = NUM2INT(bs);
}
- if (RB_TYPE_P(str, T_FIXNUM)) {
- long i;
- unsigned char bin[sizeof(long)];
- long n = FIX2LONG(str);
- unsigned long un = labs(n);
-
- for (i = sizeof(long) - 1; 0 <= i; i--) {
- bin[i] = un&0xff;
- un >>= 8;
- }
-
+ if (RB_INTEGER_TYPE_P(str)) {
GetBN(self, bn);
- if (!BN_bin2bn(bin, sizeof(bin), bn)) {
- ossl_raise(eBNError, NULL);
- }
- if (n < 0) BN_set_negative(bn, 1);
- return self;
- }
- else if (RB_TYPE_P(str, T_BIGNUM)) {
- size_t len = rb_absint_size(str, NULL);
- unsigned char *bin;
- VALUE buf;
- int sign;
-
- if (INT_MAX < len) {
- rb_raise(eBNError, "bignum too long");
- }
- bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
- sign = rb_integer_pack(str, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
+ integer_to_bnptr(str, bn);
- GetBN(self, bn);
- if (!BN_bin2bn(bin, (int)len, bn)) {
- ALLOCV_END(buf);
- ossl_raise(eBNError, NULL);
- }
- ALLOCV_END(buf);
- if (sign < 0) BN_set_negative(bn, 1);
return self;
}
+
if (RTEST(rb_obj_is_kind_of(str, cBN))) {
BIGNUM *other;
@@ -239,11 +247,11 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
*
* === Parameters
* * +base+ - integer
- * * * Valid values:
- * * * * 0 - MPI
- * * * * 2 - binary
- * * * * 10 - the default
- * * * * 16 - hex
+ * Valid values:
+ * * 0 - MPI
+ * * 2 - binary
+ * * 10 - the default
+ * * 16 - hex
*/
static VALUE
ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
@@ -346,18 +354,21 @@ ossl_bn_coerce(VALUE self, VALUE other)
/*
* Document-method: OpenSSL::BN#zero?
+ * call-seq:
* bn.zero? => true | false
*/
BIGNUM_BOOL1(is_zero)
/*
* Document-method: OpenSSL::BN#one?
+ * call-seq:
* bn.one? => true | false
*/
BIGNUM_BOOL1(is_one)
/*
* Document-method: OpenSSL::BN#odd?
+ * call-seq:
* bn.odd? => true | false
*/
BIGNUM_BOOL1(is_odd)
@@ -383,6 +394,7 @@ BIGNUM_BOOL1(is_odd)
/*
* Document-method: OpenSSL::BN#sqr
+ * call-seq:
* bn.sqr => aBN
*/
BIGNUM_1c(sqr)
@@ -408,12 +420,14 @@ BIGNUM_1c(sqr)
/*
* Document-method: OpenSSL::BN#+
+ * call-seq:
* bn + bn2 => aBN
*/
BIGNUM_2(add)
/*
* Document-method: OpenSSL::BN#-
+ * call-seq:
* bn - bn2 => aBN
*/
BIGNUM_2(sub)
@@ -439,42 +453,49 @@ BIGNUM_2(sub)
/*
* Document-method: OpenSSL::BN#*
+ * call-seq:
* bn * bn2 => aBN
*/
BIGNUM_2c(mul)
/*
* Document-method: OpenSSL::BN#%
+ * call-seq:
* bn % bn2 => aBN
*/
BIGNUM_2c(mod)
/*
* Document-method: OpenSSL::BN#**
+ * call-seq:
* bn ** bn2 => aBN
*/
BIGNUM_2c(exp)
/*
* Document-method: OpenSSL::BN#gcd
+ * call-seq:
* bn.gcd(bn2) => aBN
*/
BIGNUM_2c(gcd)
/*
* Document-method: OpenSSL::BN#mod_sqr
+ * call-seq:
* bn.mod_sqr(bn2) => aBN
*/
BIGNUM_2c(mod_sqr)
/*
* Document-method: OpenSSL::BN#mod_inverse
+ * call-seq:
* bn.mod_inverse(bn2) => aBN
*/
BIGNUM_2c(mod_inverse)
/*
* Document-method: OpenSSL::BN#/
+ * call-seq:
* bn1 / bn2 => [result, remainder]
*
* Division of OpenSSL::BN instances
@@ -529,24 +550,28 @@ ossl_bn_div(VALUE self, VALUE other)
/*
* Document-method: OpenSSL::BN#mod_add
+ * call-seq:
* bn.mod_add(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_add)
/*
* Document-method: OpenSSL::BN#mod_sub
+ * call-seq:
* bn.mod_sub(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_sub)
/*
* Document-method: OpenSSL::BN#mod_mul
+ * call-seq:
* bn.mod_mul(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_mul)
/*
* Document-method: OpenSSL::BN#mod_exp
+ * call-seq:
* bn.mod_exp(bn1, bn2) -> aBN
*/
BIGNUM_3c(mod_exp)
@@ -565,29 +590,31 @@ BIGNUM_3c(mod_exp)
/*
* Document-method: OpenSSL::BN#set_bit!
+ * call-seq:
* bn.set_bit!(bit) -> self
*/
BIGNUM_BIT(set_bit)
/*
* Document-method: OpenSSL::BN#clear_bit!
+ * call-seq:
* bn.clear_bit!(bit) -> self
*/
BIGNUM_BIT(clear_bit)
/*
* Document-method: OpenSSL::BN#mask_bit!
+ * call-seq:
* bn.mask_bit!(bit) -> self
*/
BIGNUM_BIT(mask_bits)
/* Document-method: OpenSSL::BN#bit_set?
+ * call-seq:
+ * bn.bit_set?(bit) => true | false
*
* Returns boolean of whether +bit+ is set.
* Bitwise operations for openssl BIGNUMs.
- *
- * bn.bit_set?(bit) => true | false
- *
*/
static VALUE
ossl_bn_is_bit_set(VALUE self, VALUE bit)
@@ -653,12 +680,14 @@ BIGNUM_SHIFT(rshift)
/*
* Document-method: OpenSSL::BN#lshift!
+ * call-seq:
* bn.lshift!(bits) -> self
*/
BIGNUM_SELF_SHIFT(lshift)
/*
* Document-method: OpenSSL::BN#rshift!
+ * call-seq:
* bn.rshift!(bits) -> self
*/
BIGNUM_SELF_SHIFT(rshift)
@@ -722,6 +751,7 @@ BIGNUM_RAND(pseudo_rand)
/*
* Document-method: OpenSSL::BN.rand_range
+ * call-seq:
* BN.rand_range(range) -> aBN
*
*/
@@ -729,6 +759,7 @@ BIGNUM_RAND_RANGE(rand)
/*
* Document-method: OpenSSL::BN.pseudo_rand_range
+ * call-seq:
* BN.pseudo_rand_range(range) -> aBN
*
*/
@@ -785,17 +816,19 @@ ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
{ \
BIGNUM *bn; \
GetBN(self, bn); \
- return INT2FIX(BN_##func(bn)); \
+ return INT2NUM(BN_##func(bn)); \
}
/*
* Document-method: OpenSSL::BN#num_bytes
+ * call-seq:
* bn.num_bytes => integer
*/
BIGNUM_NUM(num_bytes)
/*
* Document-method: OpenSSL::BN#num_bits
+ * call-seq:
* bn.num_bits => integer
*/
BIGNUM_NUM(num_bits)
@@ -824,21 +857,24 @@ ossl_bn_copy(VALUE self, VALUE other)
{ \
BIGNUM *bn1, *bn2 = GetBNPtr(other); \
GetBN(self, bn1); \
- return INT2FIX(BN_##func(bn1, bn2)); \
+ return INT2NUM(BN_##func(bn1, bn2)); \
}
/*
* Document-method: OpenSSL::BN#cmp
+ * call-seq:
* bn.cmp(bn2) => integer
*/
/*
* Document-method: OpenSSL::BN#<=>
+ * call-seq:
* bn <=> bn2 => integer
*/
BIGNUM_CMP(cmp)
/*
* Document-method: OpenSSL::BN#ucmp
+ * call-seq:
* bn.ucmp(bn2) => integer
*/
BIGNUM_CMP(ucmp)
@@ -921,9 +957,9 @@ 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 +nchecks+ 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 with +checks+
+ * iterations. If +nchecks+ is not specified, a number of iterations is used
+ * that yields a false positive rate of at most 2^-80 for random input.
*
* === Parameters
* * +checks+ - integer
@@ -957,8 +993,8 @@ 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 primality test. This is same as #prime? except this
+ * first attempts trial divisions with some small primes.
*
* === Parameters
* * +checks+ - integer
@@ -1001,7 +1037,8 @@ void
Init_ossl_bn(void)
{
#if 0
- mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
+ mOSSL = rb_define_module("OpenSSL");
+ eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
#endif
if (!(ossl_bn_ctx = BN_CTX_new())) {