Skip to content

Commit

Permalink
Add a draft of a primality testing function
Browse files Browse the repository at this point in the history
  • Loading branch information
est31 committed Dec 5, 2018
1 parent 1c98b67 commit 4db9e71
Show file tree
Hide file tree
Showing 8 changed files with 353 additions and 8 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ include = [
"crypto/fipsmodule/bn/internal.h",
"crypto/fipsmodule/bn/montgomery.c",
"crypto/fipsmodule/bn/montgomery_inv.c",
"crypto/fipsmodule/bn/div_extra.c",
"crypto/fipsmodule/cipher/e_aes.c",
"crypto/fipsmodule/cipher/internal.h",
"crypto/fipsmodule/ec/asm/ecp_nistz256-armv4.pl",
Expand Down Expand Up @@ -295,12 +296,13 @@ default = ["use_heap", "dev_urandom_fallback"]
dev_urandom_fallback = []
internal_benches = []
rsa_signing = ["use_heap"]
rsa_keygen = ["use_heap"]
slow_tests = []
test_logging = []
use_heap = []

[package.metadata.docs.rs]
features = [ "rsa_signing" ]
features = [ "rsa_signing", "rsa_keygen" ]

# XXX: debug = false because of https://github.com/rust-lang/rust/issues/34122

Expand Down
1 change: 1 addition & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const RING_SRCS: &[(&[&str], &str)] = &[
(&[], "crypto/fipsmodule/bn/generic.c"),
(&[], "crypto/fipsmodule/bn/montgomery.c"),
(&[], "crypto/fipsmodule/bn/montgomery_inv.c"),
(&[], "crypto/fipsmodule/bn/div_extra.c"),
(&[], "crypto/fipsmodule/cipher/e_aes.c"),
(&[], "crypto/crypto.c"),
(&[], "crypto/fipsmodule/ec/ecp_nistz.c"),
Expand Down
69 changes: 62 additions & 7 deletions crypto/fipsmodule/bn/div_extra.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */

#include <openssl/bn.h>

#include <assert.h>

#include "internal.h"
Expand Down Expand Up @@ -59,7 +57,64 @@ static uint16_t shift_and_add_mod_u16(uint16_t r, uint32_t a, uint16_t d,
return t;
}

uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d) {

// Function taken from boringssl's bn.c file.
// BN_num_bits_word returns the minimum number of bits needed to represent the
// value in |l|.
static unsigned BN_num_bits_word(BN_ULONG l) {
// |BN_num_bits| is often called on RSA prime factors. These have public bit
// lengths, but all bits beyond the high bit are secret, so count bits in
// constant time.
BN_ULONG x, mask;
int bits = (l != 0);

#if BN_BITS2 > 32
// Look at the upper half of |x|. |x| is at most 64 bits long.
x = l >> 32;
// Set |mask| to all ones if |x| (the top 32 bits of |l|) is non-zero and all
// all zeros otherwise.
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
// If |x| is non-zero, the lower half is included in the bit count in full,
// and we count the upper half. Otherwise, we count the lower half.
bits += 32 & mask;
l ^= (x ^ l) & mask; // |l| is |x| if |mask| and remains |l| otherwise.
#endif

// The remaining blocks are analogous iterations at lower powers of two.
x = l >> 16;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 16 & mask;
l ^= (x ^ l) & mask;

x = l >> 8;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 8 & mask;
l ^= (x ^ l) & mask;

x = l >> 4;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 4 & mask;
l ^= (x ^ l) & mask;

x = l >> 2;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 2 & mask;
l ^= (x ^ l) & mask;

x = l >> 1;
mask = 0u - x;
mask = (0u - (mask >> (BN_BITS2 - 1)));
bits += 1 & mask;

return bits;
}

uint16_t bn_mod_u16_consttime(const BN_ULONG bn[], size_t num_limbs, uint16_t d) {
if (d <= 1) {
return 0;
}
Expand All @@ -73,12 +128,12 @@ uint16_t bn_mod_u16_consttime(const BIGNUM *bn, uint16_t d) {
uint32_t m = ((UINT64_C(1) << (32 + p)) + d - 1) / d;

uint16_t ret = 0;
for (int i = bn->width - 1; i >= 0; i--) {
for (int i = num_limbs - 1; i >= 0; i--) {
#if BN_BITS2 == 32
ret = shift_and_add_mod_u16(ret, bn->d[i], d, p, m);
ret = shift_and_add_mod_u16(ret, bn[i], d, p, m);
#elif BN_BITS2 == 64
ret = shift_and_add_mod_u16(ret, bn->d[i] >> 32, d, p, m);
ret = shift_and_add_mod_u16(ret, bn->d[i] & 0xffffffff, d, p, m);
ret = shift_and_add_mod_u16(ret, bn[i] >> 32, d, p, m);
ret = shift_and_add_mod_u16(ret, bn[i] & 0xffffffff, d, p, m);
#else
#error "Unknown BN_ULONG size"
#endif
Expand Down
4 changes: 4 additions & 0 deletions crypto/fipsmodule/bn/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ typedef crypto_word BN_ULONG;
BN_ULONG GFp_bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w);

// bn_mod_u16_consttime returns |bn| mod |d|, ignoring |bn|'s sign bit. It runs
// in time independent of the value of |bn|, but it treats |d| as public.
OPENSSL_EXPORT uint16_t bn_mod_u16_consttime(const BN_ULONG bn[], size_t num_limbs, uint16_t d);

// |num| must be at least 4, at least on x86.
//
// In other forks, |bn_mul_mont| returns an |int| indicating whether it
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,3 +150,6 @@ mod private {
mod tests {
bssl_test!(test_constant_time, bssl_constant_time_test_main);
}

// Only here for development
pub use rsa::key_generation::probable_primality_test;
9 changes: 9 additions & 0 deletions src/limb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,17 @@ extern "C" {
fn LIMBS_less_than_limb(a: *const Limb, b: Limb, num_limbs: c::size_t) -> LimbMask;
fn LIMBS_reduce_once(r: *mut Limb, m: *const Limb, num_limbs: c::size_t);
fn LIMB_shr(a: Limb, shift: c::size_t) -> Limb;
fn bn_mod_u16_consttime(bn: *const Limb, num_limbs: c::size_t, d: u16) -> u16;
}

pub fn mod_u16_consttime(limbs: &[Limb], d: u16) -> u16 {
unsafe {
bn_mod_u16_consttime(limbs.as_ptr(), limbs.len(), d)
}
}



#[cfg(test)]
mod tests {
use super::*;
Expand Down
Loading

0 comments on commit 4db9e71

Please sign in to comment.