Replace crypto/bn/random.c with Rust code.

This commit is contained in:
Brian Smith 2017-04-25 00:10:02 -10:00
parent 0f8fe6ef36
commit f9528db33e
9 changed files with 54 additions and 230 deletions

View File

@ -158,7 +158,6 @@ include = [
"crypto/bn/montgomery.c",
"crypto/bn/montgomery_inv.c",
"crypto/bn/mul.c",
"crypto/bn/random.c",
"crypto/bn/shift.c",
"crypto/chacha/asm/chacha-armv4.pl",
"crypto/chacha/asm/chacha-armv8.pl",

View File

@ -93,7 +93,6 @@ const RING_SRCS: &'static [(&'static [&'static str], &'static str)] = &[
(&[], "crypto/bn/montgomery.c"),
(&[], "crypto/bn/montgomery_inv.c"),
(&[], "crypto/bn/mul.c"),
(&[], "crypto/bn/random.c"),
(&[], "crypto/bn/shift.c"),
(&[], "crypto/cipher/e_aes.c"),
(&[], "crypto/crypto.c"),

View File

@ -1,132 +0,0 @@
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/
/* ====================================================================
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com). */
#include <GFp/bn.h>
#include <assert.h>
#include <GFp/err.h>
int GFp_BN_rand_range_ex(BIGNUM *r, const BIGNUM *max_exclusive, RAND *rng) {
assert(!GFp_BN_is_zero(max_exclusive));
assert(!GFp_BN_is_one(max_exclusive));
if (!GFp_bn_wexpand(r, max_exclusive->top)) {
return 0;
}
if (!GFp_rand_mod(r->d, max_exclusive->d, max_exclusive->top, rng)) {
return 0;
}
r->top = max_exclusive->top;
GFp_bn_correct_top(r);
return 1;
}

View File

@ -269,18 +269,6 @@ OPENSSL_EXPORT int GFp_BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, const BIGNUM *m);
/* Random generation. */
extern int GFp_rand_mod(BN_ULONG *dest, const BN_ULONG *max_exclusive,
size_t num_limbs, RAND *rand);
/* GFp_BN_rand_range_ex sets |rnd| to a random value in [1..max_exclusive). It
* returns one on success and zero otherwise. */
OPENSSL_EXPORT int GFp_BN_rand_range_ex(BIGNUM *r, const BIGNUM *max_exclusive,
RAND *rng);
/* Number theory functions */
/* GFp_BN_mod_inverse_odd sets |out| equal to |a|^-1, mod |n|. |a| must be

View File

@ -159,12 +159,6 @@ pub mod rand;
#[path = "rsa/rsa.rs"]
mod rsa;
// Really a private method; only has public visibility so that C compilation
// can see it.
#[cfg(feature = "use_heap")]
#[doc(hidden)]
pub use rsa::GFp_rand_mod;
pub mod signature;
#[cfg(any(feature = "use_heap", test))]

View File

@ -286,19 +286,6 @@ mod darwin {
}
}
/// An adapter that lets the C code use `SecureRandom`.
#[allow(non_snake_case)]
#[doc(hidden)]
pub struct RAND<'a> {
pub rng: &'a SecureRandom,
}
impl<'a> RAND<'a> {
/// Wraps `rng` in a `RAND` so it can be passed to non-Rust code.
pub fn new(rng: &'a SecureRandom) -> RAND<'a> { RAND { rng: rng } }
}
#[cfg(test)]
mod tests {
use rand;

View File

@ -564,25 +564,26 @@ pub fn elem_exp_consttime<M>(
Ok(r)
}
pub fn elem_randomize<M, E>(a: &mut Elem<M, E>, m: &Modulus<M>,
rng: &rand::SecureRandom)
-> Result<(), error::Unspecified> {
a.value.randomize(m.value.as_ref(), rng)
pub fn elem_randomize<E>(a: &mut Elem<super::N, E>, m: &Modulus<super::N>,
rng: &rand::SecureRandom)
-> Result<(), error::Unspecified> {
a.value.randomize(m, rng)
}
// r = 1/a (mod m), blinded with a random element.
//
// This relies on the invariants of `Modulus` that its value is odd and larger
// than one.
pub fn elem_set_to_inverse_blinded<M>(
r: &mut Elem<M, R>, a: &Elem<M, Unencoded>, m: &Modulus<M>,
rng: &rand::SecureRandom) -> Result<(), InversionError> {
let mut blinding_factor = try!(Elem::<M, R>::zero());
try!(blinding_factor.value.randomize(m.value.as_ref(), rng));
pub fn elem_set_to_inverse_blinded(
r: &mut Elem<super::N, R>, a: &Elem<super::N, Unencoded>,
n: &Modulus<super::N>, rng: &rand::SecureRandom)
-> Result<(), InversionError> {
let mut blinding_factor = try!(Elem::<super::N, R>::zero());
try!(elem_randomize(&mut blinding_factor, n, rng));
let to_blind = try!(a.try_clone());
let blinded = try!(elem_mul(&blinding_factor, to_blind, m));
let blinded_inverse = try!(elem_inverse(blinded, m));
try!(elem_set_to_product(r, &blinding_factor, &blinded_inverse, m));
let blinded = try!(elem_mul(&blinding_factor, to_blind, n));
let blinded_inverse = try!(elem_inverse(blinded, n));
try!(elem_set_to_product(r, &blinding_factor, &blinded_inverse, n));
Ok(())
}
@ -794,11 +795,11 @@ impl Nonnegative {
Ok(())
}
fn randomize(&mut self, m: &BIGNUM, rng: &rand::SecureRandom)
fn randomize(&mut self, m: &Modulus<super::N>, rng: &rand::SecureRandom)
-> Result<(), error::Unspecified> {
let mut rand = rand::RAND::new(rng);
bssl::map_result(unsafe {
GFp_BN_rand_range_ex(self.as_mut_ref(), m, &mut rand)
let m = (m.value.0).0.limbs();
self.0.make_limbs(m.len(), |limbs| {
super::random::set_to_rand_mod(limbs, m, rng)
})
}
@ -929,9 +930,26 @@ mod repr_c {
self.top -= 1;
}
}
pub fn make_limbs<F>(&mut self, num_limbs: usize, f: F)
-> Result<(), error::Unspecified>
where F: FnOnce(&mut [limb::Limb])
-> Result<(), error::Unspecified> {
let num_limbs = num_limbs as c::int; // XXX
try!(bssl::map_result(unsafe {
GFp_bn_wexpand(self, num_limbs)
}));
self.top = num_limbs;
try!(f(self.limbs_mut()));
unsafe {
GFp_bn_correct_top(self)
}
Ok(())
}
}
extern {
fn GFp_bn_correct_top(r: &mut BIGNUM);
fn GFp_bn_wexpand(r: &mut BIGNUM, words: c::int) -> c::int;
}
}
@ -975,12 +993,6 @@ extern {
n0: &N0) -> c::int;
}
#[allow(improper_ctypes)]
extern {
fn GFp_BN_rand_range_ex(r: &mut BIGNUM, max_exclusive: &BIGNUM,
rng: &mut rand::RAND) -> c::int;
}
#[cfg(test)]
mod tests {
use super::*;
@ -1088,20 +1100,22 @@ mod tests {
#[test]
fn test_elem_set_to_inverse_blinded_invertible() {
use super::super::N;
let rng = rand::SystemRandom::new();
test::from_file("src/rsa/bigint_elem_inverse_invertible_tests.txt",
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M");
let a = consume_elem(test_case, "A", &m);
let expected_result = consume_elem(test_case, "R", &m);
let mut actual_result = try!(Elem::<M, R>::zero());
assert!(elem_set_to_inverse_blinded(&mut actual_result, &a, &m,
let n = consume_modulus::<N>(test_case, "M");
let a = consume_elem(test_case, "A", &n);
let expected_result = consume_elem(test_case, "R", &n);
let mut actual_result = try!(Elem::<N, R>::zero());
assert!(elem_set_to_inverse_blinded(&mut actual_result, &a, &n,
&rng).is_ok());
let one: Elem<M, Unencoded> = try!(Elem::one());
let actual_result = try!(elem_mul(&one, actual_result, &m));
let one: Elem<N, Unencoded> = try!(Elem::one());
let actual_result = try!(elem_mul(&one, actual_result, &n));
assert_elem_eq(&actual_result, &expected_result);
Ok(())
})
@ -1126,16 +1140,18 @@ mod tests {
#[test]
fn test_elem_set_to_inverse_blinded_noninvertible() {
use super::super::N;
let rng = rand::SystemRandom::new();
test::from_file("src/rsa/bigint_elem_inverse_noninvertible_tests.txt",
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M");
let a = consume_elem(test_case, "A", &m);
let mut actual_result = try!(Elem::<M, R>::zero());
match elem_set_to_inverse_blinded(&mut actual_result, &a, &m, &rng) {
let n = consume_modulus::<N>(test_case, "M");
let a = consume_elem(test_case, "A", &n);
let mut actual_result = try!(Elem::<N, R>::zero());
match elem_set_to_inverse_blinded(&mut actual_result, &a, &n, &rng) {
Err(InversionError::NoInverse) => (),
Err(InversionError::Unspecified) => unreachable!("Unspecified"),
Ok(..) => unreachable!("No error"),

View File

@ -16,35 +16,13 @@
//! Generation of random field elements, in particular field elements in GFn
//! where *n* is an RSA public modulus.
use {c, core, rand, error, rsa};
use {rand, error, rsa};
use limb::*;
/// Sets `out`, which has `num_limbs` limbs, to a random value in the range
/// [1, `max_exclusive`), where `max_exclusive` also has `num_limbs` limbs.
#[doc(hidden)]
#[no_mangle]
pub unsafe extern fn GFp_rand_mod(out: *mut Limb, max_exclusive: *const Limb,
num_limbs: c::size_t, rng: *mut rand::RAND)
-> c::int {
const ERR: c::int = 0;
const SUCCESS: c::int = 1;
let max_exclusive = core::slice::from_raw_parts(max_exclusive, num_limbs);
let mut out = core::slice::from_raw_parts_mut(out, num_limbs);
let result = set_to_rand_mod(&mut out, &max_exclusive, (*rng).rng);
if result.is_err() {
return ERR;
}
SUCCESS
}
/// Chooses a positive integer less than `max_exclusive` uniformly at random
/// and stores it into `out`.
fn set_to_rand_mod(out: &mut [Limb], max_exclusive: &[Limb],
rng: &rand::SecureRandom)
-> Result<(), error::Unspecified> {
/// Sets `out` to a *uniformly* random value in the range [1, `max_exclusive`).
pub fn set_to_rand_mod(out: &mut [Limb], max_exclusive: &[Limb],
rng: &rand::SecureRandom)
-> Result<(), error::Unspecified> {
assert_eq!(out.len(), max_exclusive.len());
assert!(out.len() >= 1);
assert!(out.len() <= rsa::PRIVATE_KEY_PUBLIC_MODULUS_MAX_LIMBS);

View File

@ -148,8 +148,3 @@ mod bigint;
mod blinding;
mod random;
// Really a private method; only has public visibility so that C compilation
// can see it.
#[doc(hidden)]
pub use rsa::random::GFp_rand_mod;