Start on error + BN refactor
This commit is contained in:
parent
fdb4131064
commit
8f89f0bfa9
|
|
@ -2,9 +2,10 @@ use libc::c_long;
|
||||||
use std::{ptr, fmt};
|
use std::{ptr, fmt};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use bio::MemBio;
|
|
||||||
use ffi;
|
use ffi;
|
||||||
|
|
||||||
|
use {cvt, cvt_p};
|
||||||
|
use bio::MemBio;
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
|
|
||||||
/// Corresponds to the ASN.1 structure Time defined in RFC5280
|
/// Corresponds to the ASN.1 structure Time defined in RFC5280
|
||||||
|
|
@ -20,7 +21,7 @@ impl Asn1Time {
|
||||||
ffi::init();
|
ffi::init();
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let handle = try_ssl_null!(ffi::X509_gmtime_adj(ptr::null_mut(), period));
|
let handle = try!(cvt_p(ffi::X509_gmtime_adj(ptr::null_mut(), period)));
|
||||||
Ok(Asn1Time::from_ptr(handle))
|
Ok(Asn1Time::from_ptr(handle))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -58,7 +59,7 @@ impl<'a> fmt::Display for Asn1TimeRef<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
let mem_bio = try!(MemBio::new());
|
let mem_bio = try!(MemBio::new());
|
||||||
let as_str = unsafe {
|
let as_str = unsafe {
|
||||||
try_ssl!(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.0));
|
try!(cvt(ffi::ASN1_TIME_print(mem_bio.as_ptr(), self.0)));
|
||||||
String::from_utf8_unchecked(mem_bio.get_buf().to_owned())
|
String::from_utf8_unchecked(mem_bio.get_buf().to_owned())
|
||||||
};
|
};
|
||||||
write!(f, "{}", as_str)
|
write!(f, "{}", as_str)
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
|
use ffi;
|
||||||
use libc::{c_int, c_void};
|
use libc::{c_int, c_void};
|
||||||
use std::ffi::{CStr, CString};
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
use std::ffi::{CStr, CString};
|
||||||
use std::{fmt, ptr};
|
use std::{fmt, ptr};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref, DerefMut};
|
use std::ops::{Add, Div, Mul, Neg, Rem, Shl, Shr, Sub, Deref, DerefMut};
|
||||||
|
|
||||||
use ffi;
|
use {cvt, cvt_p, cvt_n};
|
||||||
use error::ErrorStack;
|
use error::ErrorStack;
|
||||||
|
|
||||||
/// Specifies the desired properties of a randomly generated `BigNum`.
|
/// Specifies the desired properties of a randomly generated `BigNum`.
|
||||||
|
|
@ -74,199 +75,141 @@ macro_rules! with_bn_in_ctx(
|
||||||
});
|
});
|
||||||
);
|
);
|
||||||
|
|
||||||
/// A borrowed, signed, arbitrary-precision integer.
|
/// A context object for `BigNum` operations.
|
||||||
#[derive(Copy, Clone)]
|
pub struct BnCtx(*mut ffi::BN_CTX);
|
||||||
pub struct BigNumRef<'a>(*mut ffi::BIGNUM, PhantomData<&'a ()>);
|
|
||||||
|
|
||||||
|
impl Drop for BnCtx {
|
||||||
impl<'a> BigNumRef<'a> {
|
fn drop(&mut self) {
|
||||||
pub unsafe fn from_ptr(handle: *mut ffi::BIGNUM) -> BigNumRef<'a> {
|
|
||||||
BigNumRef(handle, PhantomData)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the square of `self`.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use openssl::bn::BigNum;
|
|
||||||
/// let ref n = BigNum::new_from(10).unwrap();
|
|
||||||
/// let squared = BigNum::new_from(100).unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(n.checked_sqr().unwrap(), squared);
|
|
||||||
/// assert_eq!(n * n, squared);
|
|
||||||
/// ```
|
|
||||||
pub fn checked_sqr(&self) -> Result<BigNum, ErrorStack> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
ffi::BN_CTX_free(self.0);
|
||||||
ffi::BN_sqr(r.as_ptr(), self.as_ptr(), ctx) == 1
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the unsigned remainder of the division `self / n`.
|
impl BnCtx {
|
||||||
pub fn checked_nnmod(&self, n: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
/// Returns a new `BnCtx`.
|
||||||
|
pub fn new() -> Result<BnCtx, ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt_p(ffi::BN_CTX_new()).map(BnCtx)
|
||||||
ffi::BN_nnmod(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to `(self + a) mod n`.
|
/// Places the result of `a²` in `r`.
|
||||||
///
|
pub fn sqr(&mut self, r: &mut BigNumRef, a: &BigNumRef) -> Result<(), ErrorStack> {
|
||||||
/// ```
|
|
||||||
/// # use openssl::bn::BigNum;
|
|
||||||
/// let ref s = BigNum::new_from(10).unwrap();
|
|
||||||
/// let ref a = BigNum::new_from(20).unwrap();
|
|
||||||
/// let ref n = BigNum::new_from(29).unwrap();
|
|
||||||
/// let result = BigNum::new_from(1).unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(s.checked_mod_add(a, n).unwrap(), result);
|
|
||||||
/// ```
|
|
||||||
pub fn checked_mod_add(&self, a: &BigNumRef, n: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_sqr(r.as_ptr(), a.as_ptr(), self.0)).map(|_| ())
|
||||||
ffi::BN_mod_add(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to `(self - a) mod n`.
|
/// Places the result of `a mod m` in `r`.
|
||||||
pub fn checked_mod_sub(&self, a: &BigNumRef, n: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
pub fn nnmod(&mut self,
|
||||||
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
m: &BigNumRef) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_nnmod(r.as_ptr(), a.as_ptr(), m.as_ptr(), self.0)).map(|_| ())
|
||||||
ffi::BN_mod_sub(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to `(self * a) mod n`.
|
/// Places the result of `(a + b) mod m` in `r`.
|
||||||
pub fn checked_mod_mul(&self, a: &BigNumRef, n: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
pub fn mod_add(&mut self,
|
||||||
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
b: &BigNumRef,
|
||||||
|
m: &BigNumRef)
|
||||||
|
-> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_mod_add(r.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), self.0)).map(|_| ())
|
||||||
ffi::BN_mod_mul(r.as_ptr(), self.as_ptr(), a.as_ptr(), n.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to `self² mod n`.
|
/// Places the result of `(a - b) mod m` in `r`.
|
||||||
pub fn checked_mod_sqr(&self, n: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
pub fn mod_sub(&mut self,
|
||||||
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
b: &BigNumRef,
|
||||||
|
m: &BigNumRef)
|
||||||
|
-> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_mod_sub(r.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), self.0)).map(|_| ())
|
||||||
ffi::BN_mod_sqr(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Raises `self` to the `p`th power.
|
/// Places the result of `(a * b) mod m` in `r`.
|
||||||
pub fn checked_exp(&self, p: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
pub fn mod_mul(&mut self,
|
||||||
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
b: &BigNumRef,
|
||||||
|
m: &BigNumRef)
|
||||||
|
-> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_mod_mul(r.as_ptr(), a.as_ptr(), b.as_ptr(), m.as_ptr(), self.0)).map(|_| ())
|
||||||
ffi::BN_exp(r.as_ptr(), self.as_ptr(), p.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Equivalent to `self.checked_exp(p) mod n`.
|
/// Places the result of `a² mod m` in `r`.
|
||||||
pub fn checked_mod_exp(&self, p: &BigNumRef, n: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
pub fn mod_sqr(&mut self,
|
||||||
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
m: &BigNumRef) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_mod_sqr(r.as_ptr(), a.as_ptr(), m.as_ptr(), self.0)).map(|_| ())
|
||||||
ffi::BN_mod_exp(r.as_ptr(), self.as_ptr(), p.as_ptr(), n.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the modular multiplicative inverse of `self` modulo `n`, that is, an integer `r`
|
/// Places the result of `a^p` in `r`.
|
||||||
/// such that `(self * r) % n == 1`.
|
pub fn exp(&mut self,
|
||||||
pub fn checked_mod_inv(&self, n: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
p: &BigNumRef) -> Result<(), ErrorStack> {
|
||||||
unsafe{
|
unsafe{
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_exp(r.as_ptr(), a.as_ptr(), p.as_ptr(), self.0)).map(|_| ())
|
||||||
!ffi::BN_mod_inverse(r.as_ptr(), self.as_ptr(), n.as_ptr(), ctx).is_null()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a `u32` to `self`. This is more efficient than adding a
|
/// Places the result of `a^p mod m` in `r`.
|
||||||
/// `BigNum`.
|
pub fn mod_exp(&mut self,
|
||||||
pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
p: &BigNumRef,
|
||||||
|
m: &BigNumRef) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::BN_add_word(self.as_ptr(), w as ffi::BN_ULONG) == 1 {
|
cvt(ffi::BN_mod_exp(r.as_ptr(), a.as_ptr(), p.as_ptr(), m.as_ptr(), self.0)).map(|_| ())
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
/// Places the inverse of `a` modulo `n` in `r`.
|
||||||
|
pub fn mod_inverse(&mut self,
|
||||||
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
n: &BigNumRef) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::BN_sub_word(self.as_ptr(), w as ffi::BN_ULONG) == 1 {
|
cvt_p(ffi::BN_mod_inverse(r.0, a.0, n.0, self.0)).map(|_| ())
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
/// Places the greatest common denominator of `a` and `b` in `r`.
|
||||||
|
pub fn gcd(&mut self,
|
||||||
|
r: &mut BigNumRef,
|
||||||
|
a: &BigNumRef,
|
||||||
|
b: &BigNumRef) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::BN_mul_word(self.as_ptr(), w as ffi::BN_ULONG) == 1 {
|
cvt(ffi::BN_gcd(r.0, a.0, b.0, self.0)).map(|_| ())
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
let result = ffi::BN_div_word(self.as_ptr(), w as ffi::BN_ULONG);
|
|
||||||
if result != !0 {
|
|
||||||
Ok(result.into())
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
let result = ffi::BN_mod_word(self.as_ptr(), w as ffi::BN_ULONG);
|
|
||||||
if result != !0 {
|
|
||||||
Ok(result as u64)
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the greatest common denominator of `self` and `a`.
|
|
||||||
pub fn checked_gcd(&self, a: &BigNumRef) -> Result<BigNum, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
with_bn_in_ctx!(r, ctx, {
|
|
||||||
ffi::BN_gcd(r.as_ptr(), self.as_ptr(), a.as_ptr(), ctx) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether `self` is prime.
|
/// Checks whether `p` is prime.
|
||||||
///
|
///
|
||||||
/// Performs a Miller-Rabin probabilistic primality test with `checks` iterations.
|
/// Performs a Miller-Rabin probabilistic primality test with `checks` iterations.
|
||||||
///
|
///
|
||||||
/// # Return Value
|
/// Returns `true` if `p` is prime with an error probability of less than `0.25 ^ checks`.
|
||||||
///
|
pub fn is_prime(&mut self, p: &BigNumRef, checks: i32) -> Result<bool, ErrorStack> {
|
||||||
/// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
|
|
||||||
pub fn is_prime(&self, checks: i32) -> Result<bool, ErrorStack> {
|
|
||||||
unsafe {
|
unsafe {
|
||||||
with_ctx!(ctx, {
|
cvt_n(ffi::BN_is_prime_ex(p.0, checks.into(), self.0, ptr::null_mut())).map(|r| r != 0)
|
||||||
Ok(ffi::BN_is_prime_ex(self.as_ptr(),
|
|
||||||
checks as c_int,
|
|
||||||
ctx,
|
|
||||||
ptr::null_mut()) == 1)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks whether `self` is prime with optional trial division.
|
/// Checks whether `p` is prime with optional trial division.
|
||||||
///
|
///
|
||||||
/// If `do_trial_division` is `true`, first performs trial division by a number of small primes.
|
/// If `do_trial_division` is `true`, first performs trial division by a number of small primes.
|
||||||
/// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks`
|
/// Then, like `is_prime`, performs a Miller-Rabin probabilistic primality test with `checks`
|
||||||
|
|
@ -274,35 +217,88 @@ impl<'a> BigNumRef<'a> {
|
||||||
///
|
///
|
||||||
/// # Return Value
|
/// # Return Value
|
||||||
///
|
///
|
||||||
/// Returns `true` if `self` is prime with an error probability of less than `0.25 ^ checks`.
|
/// Returns `true` if `p` is prime with an error probability of less than `0.25 ^ checks`.
|
||||||
pub fn is_prime_fast(&self, checks: i32, do_trial_division: bool) -> Result<bool, ErrorStack> {
|
pub fn is_prime_fasttest(&mut self,
|
||||||
|
p: &BigNumRef,
|
||||||
|
checks: i32,
|
||||||
|
do_trial_division: bool) -> Result<bool, ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_ctx!(ctx, {
|
cvt_n(ffi::BN_is_prime_fasttest_ex(p.0,
|
||||||
Ok(ffi::BN_is_prime_fasttest_ex(self.as_ptr(),
|
checks.into(),
|
||||||
checks as c_int,
|
self.0,
|
||||||
ctx,
|
|
||||||
do_trial_division as c_int,
|
do_trial_division as c_int,
|
||||||
ptr::null_mut()) == 1)
|
ptr::null_mut()))
|
||||||
})
|
.map(|r| r != 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates a cryptographically strong pseudo-random `BigNum` `r` in the range
|
/// A borrowed, signed, arbitrary-precision integer.
|
||||||
/// `0 <= r < self`.
|
#[derive(Copy, Clone)]
|
||||||
pub fn checked_rand_in_range(&self) -> Result<BigNum, ErrorStack> {
|
pub struct BigNumRef<'a>(*mut ffi::BIGNUM, PhantomData<&'a ()>);
|
||||||
|
|
||||||
|
impl<'a> BigNumRef<'a> {
|
||||||
|
pub unsafe fn from_ptr(handle: *mut ffi::BIGNUM) -> BigNumRef<'a> {
|
||||||
|
BigNumRef(handle, PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a `u32` to `self`.
|
||||||
|
pub fn add_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_add_word(self.0, w as ffi::BN_ULONG)).map(|_| ())
|
||||||
ffi::BN_rand_range(r.as_ptr(), self.as_ptr()) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The cryptographically weak counterpart to `checked_rand_in_range`.
|
/// Subtracts a `u32` from `self`.
|
||||||
pub fn checked_pseudo_rand_in_range(&self) -> Result<BigNum, ErrorStack> {
|
pub fn sub_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn_in_ctx!(r, ctx, {
|
cvt(ffi::BN_sub_word(self.0, w as ffi::BN_ULONG)).map(|_| ())
|
||||||
ffi::BN_pseudo_rand_range(r.as_ptr(), self.as_ptr()) == 1
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
/// Multiplies a `u32` by `self`.
|
||||||
|
pub fn mul_word(&mut self, w: u32) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::BN_mul_word(self.0, w as ffi::BN_ULONG)).map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Divides `self` by a `u32`, returning the remainder.
|
||||||
|
pub fn div_word(&mut self, w: u32) -> Result<u64, ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
let r = ffi::BN_div_word(self.0, w.into());
|
||||||
|
if r == ffi::BN_ULONG::max_value() {
|
||||||
|
Err(ErrorStack::get())
|
||||||
|
} else {
|
||||||
|
Ok(r.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the result of `self` modulo `w`.
|
||||||
|
pub fn mod_word(&self, w: u32) -> Result<u64, ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
let r = ffi::BN_mod_word(self.0, w.into());
|
||||||
|
if r == ffi::BN_ULONG::max_value() {
|
||||||
|
Err(ErrorStack::get())
|
||||||
|
} else {
|
||||||
|
Ok(r.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Places a cryptographically-secure pseudo-random number nonnegative
|
||||||
|
/// number less than `self` in `rnd`.
|
||||||
|
pub fn rand_in_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::BN_rand_range(self.0, rnd.0)).map(|_| ())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The cryptographically weak counterpart to `rand_in_range`.
|
||||||
|
pub fn pseudo_rand_in_range(&self, rnd: &mut BigNumRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::BN_pseudo_rand_range(self.0, rnd.0)).map(|_| ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -311,11 +307,7 @@ impl<'a> BigNumRef<'a> {
|
||||||
/// When setting a bit outside of `self`, it is expanded.
|
/// When setting a bit outside of `self`, it is expanded.
|
||||||
pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
|
pub fn set_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::BN_set_bit(self.as_ptr(), n as c_int) == 1 {
|
cvt(ffi::BN_set_bit(self.0, n.into())).map(|_| ())
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -324,17 +316,15 @@ impl<'a> BigNumRef<'a> {
|
||||||
/// When clearing a bit outside of `self`, an error is returned.
|
/// When clearing a bit outside of `self`, an error is returned.
|
||||||
pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
|
pub fn clear_bit(&mut self, n: i32) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::BN_clear_bit(self.as_ptr(), n as c_int) == 1 {
|
cvt(ffi::BN_clear_bit(self.0, n.into())).map(|_| ())
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise.
|
/// Returns `true` if the `n`th bit of `self` is set to 1, `false` otherwise.
|
||||||
pub fn is_bit_set(&self, n: i32) -> bool {
|
pub fn is_bit_set(&self, n: i32) -> bool {
|
||||||
unsafe { ffi::BN_is_bit_set(self.as_ptr(), n as c_int) == 1 }
|
unsafe {
|
||||||
|
ffi::BN_is_bit_set(self.0, n.into()) == 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Truncates `self` to the lowest `n` bits.
|
/// Truncates `self` to the lowest `n` bits.
|
||||||
|
|
@ -342,46 +332,21 @@ impl<'a> BigNumRef<'a> {
|
||||||
/// An error occurs if `self` is already shorter than `n` bits.
|
/// An error occurs if `self` is already shorter than `n` bits.
|
||||||
pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
|
pub fn mask_bits(&mut self, n: i32) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if ffi::BN_mask_bits(self.as_ptr(), n as c_int) == 1 {
|
cvt(ffi::BN_mask_bits(self.0, n.into())).map(|_| ())
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(ErrorStack::get())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns `self`, shifted left by 1 bit. `self` may be negative.
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use openssl::bn::BigNum;
|
|
||||||
/// let ref s = BigNum::new_from(0b0100).unwrap();
|
|
||||||
/// let result = BigNum::new_from(0b1000).unwrap();
|
|
||||||
///
|
|
||||||
/// assert_eq!(s.checked_shl1().unwrap(), result);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// # use openssl::bn::BigNum;
|
|
||||||
/// let ref s = -BigNum::new_from(8).unwrap();
|
|
||||||
/// let result = -BigNum::new_from(16).unwrap();
|
|
||||||
///
|
|
||||||
/// // (-8) << 1 == -16
|
|
||||||
/// assert_eq!(s.checked_shl1().unwrap(), result);
|
|
||||||
/// ```
|
|
||||||
pub fn checked_shl1(&self) -> Result<BigNum, ErrorStack> {
|
|
||||||
unsafe {
|
|
||||||
with_bn!(r, {
|
|
||||||
ffi::BN_lshift1(r.as_ptr(), self.as_ptr()) == 1
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `self`, shifted right by 1 bit. `self` may be negative.
|
/// Places `self << 1` in `r`.
|
||||||
pub fn checked_shr1(&self) -> Result<BigNum, ErrorStack> {
|
pub fn lshift1(&self, r: &mut BigNumRef) -> Result<(), ErrorStack> {
|
||||||
unsafe {
|
unsafe {
|
||||||
with_bn!(r, {
|
cvt(ffi::BN_lshift1(r.0, self.0)).map(|_| ())
|
||||||
ffi::BN_rshift1(r.as_ptr(), self.as_ptr()) == 1
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
/// Places `self >> 1` in `r`.
|
||||||
|
pub fn rshift1(&self, r: &mut BigNumRef) -> Result<(), ErrorStack> {
|
||||||
|
unsafe {
|
||||||
|
cvt(ffi::BN_rshift1(r.0, self.0)).map(|_| ())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1006,7 +971,7 @@ impl Neg for BigNum {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use bn::BigNum;
|
use bn::{BnCtx, BigNum};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_to_from_slice() {
|
fn test_to_from_slice() {
|
||||||
|
|
@ -1031,7 +996,8 @@ mod tests {
|
||||||
let a = BigNum::new_from(19029017).unwrap();
|
let a = BigNum::new_from(19029017).unwrap();
|
||||||
let p = BigNum::checked_generate_prime(128, true, None, Some(&a)).unwrap();
|
let p = BigNum::checked_generate_prime(128, true, None, Some(&a)).unwrap();
|
||||||
|
|
||||||
assert!(p.is_prime(100).unwrap());
|
let mut ctx = BnCtx::new().unwrap();
|
||||||
assert!(p.is_prime_fast(100, true).unwrap());
|
assert!(ctx.is_prime(&p, 100).unwrap());
|
||||||
|
assert!(ctx.is_prime_fasttest(&p, 100, true).unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,7 +135,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dh_from_pem() {
|
fn test_dh_from_pem() {
|
||||||
let mut ctx = SslContext::new(SslMethod::tls()).unwrap();
|
let mut ctx = SslContext::new(SslMethod::tls()).unwrap();
|
||||||
let params = include_bytes!("../../test/dhparams.pem");
|
let params = include_bytes!("../test/dhparams.pem");
|
||||||
let dh = DH::from_pem(params).ok().expect("Failed to load PEM");
|
let dh = DH::from_pem(params).ok().expect("Failed to load PEM");
|
||||||
ctx.set_tmp_dh(&dh).unwrap();
|
ctx.set_tmp_dh(&dh).unwrap();
|
||||||
}
|
}
|
||||||
|
|
@ -16,6 +16,10 @@ extern crate tempdir;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use ffi::init;
|
pub use ffi::init;
|
||||||
|
|
||||||
|
use libc::c_int;
|
||||||
|
|
||||||
|
use error::ErrorStack;
|
||||||
|
|
||||||
mod macros;
|
mod macros;
|
||||||
|
|
||||||
pub mod asn1;
|
pub mod asn1;
|
||||||
|
|
@ -28,3 +32,27 @@ pub mod nid;
|
||||||
pub mod ssl;
|
pub mod ssl;
|
||||||
pub mod version;
|
pub mod version;
|
||||||
pub mod x509;
|
pub mod x509;
|
||||||
|
|
||||||
|
pub fn cvt_p<T>(r: *mut T) -> Result<*mut T, ErrorStack> {
|
||||||
|
if r.is_null() {
|
||||||
|
Err(ErrorStack::get())
|
||||||
|
} else {
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cvt(r: c_int) -> Result<c_int, ErrorStack> {
|
||||||
|
if r <= 0 {
|
||||||
|
Err(ErrorStack::get())
|
||||||
|
} else {
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cvt_n(r: c_int) -> Result<c_int, ErrorStack> {
|
||||||
|
if r < 0 {
|
||||||
|
Err(ErrorStack::get())
|
||||||
|
} else {
|
||||||
|
Ok(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue