Remove non-Montgomery multiplication.

This commit is contained in:
Brian Smith 2018-05-03 16:47:48 -10:00
parent 41abee65e6
commit df505089ee
9 changed files with 81 additions and 281 deletions

View File

@ -63,7 +63,6 @@ const RING_SRCS: &'static [(&'static [&'static str], &'static str)] = &[
(&[], "crypto/fipsmodule/bn/generic.c"),
(&[], "crypto/fipsmodule/bn/montgomery.c"),
(&[], "crypto/fipsmodule/bn/montgomery_inv.c"),
(&[], "crypto/fipsmodule/bn/mul.c"),
(&[], "crypto/fipsmodule/bn/shift.c"),
(&[], "crypto/fipsmodule/cipher/e_aes.c"),
(&[NEVER], "crypto/cipher_extra/e_aesgcmsiv.c"),

View File

@ -64,23 +64,6 @@
#include "internal.h"
void GFp_BN_init(BIGNUM *bn) {
memset(bn, 0, sizeof(BIGNUM));
}
void GFp_BN_free(BIGNUM *bn) {
// Keep this in sync with the |Drop| impl for |BIGNUM| in
// |ring::rsa::bigint|.
if (bn == NULL) {
return;
}
OPENSSL_free(bn->d);
bn->d = NULL;
}
int GFp_BN_copy(BIGNUM *dest, const BIGNUM *src) {
if (src == dest) {
return 1;
@ -98,10 +81,6 @@ int GFp_BN_copy(BIGNUM *dest, const BIGNUM *src) {
return 1;
}
void GFp_BN_zero(BIGNUM *bn) {
bn->top = 0;
}
int GFp_bn_wexpand(BIGNUM *bn, size_t words) {
BN_ULONG *a;

View File

@ -258,7 +258,7 @@ int GFp_BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a_mont,
unsigned char *powerbuf = NULL;
const int top = n->top;
if (!GFp_bn_mul_mont_check_top(top)) {
if (!GFp_bn_mul_mont_check_num_limbs(top)) {
goto err;
}

View File

@ -72,23 +72,6 @@
(r) = ret; \
} while (0)
#define mul(r, a, w, c) \
do { \
BN_ULONG high, low, ret, ta = (a); \
bn_umult_lohi(&low, &high, w, ta); \
ret = low + (c); \
(c) = high; \
(c) += (ret < low) ? 1 : 0; \
(r) = ret; \
} while (0)
#define sqr(r0, r1, a) \
do { \
BN_ULONG tmp = (a); \
bn_umult_lohi(&r0, &r1, tmp, tmp); \
} while (0)
BN_ULONG GFp_bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w) {
BN_ULONG c1 = 0;
@ -116,29 +99,3 @@ BN_ULONG GFp_bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
return c1;
}
BN_ULONG GFp_bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w) {
BN_ULONG c1 = 0;
if (num == 0) {
return c1;
}
while (num & ~3) {
mul(rp[0], ap[0], w, c1);
mul(rp[1], ap[1], w, c1);
mul(rp[2], ap[2], w, c1);
mul(rp[3], ap[3], w, c1);
ap += 4;
rp += 4;
num -= 4;
}
while (num) {
mul(rp[0], ap[0], w, c1);
ap++;
rp++;
num--;
}
return c1;
}

View File

@ -178,12 +178,6 @@ extern "C" {
BN_ULONG GFp_bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w);
// bn_mul_words multiples |ap| by |w| and places the result in |rp|. |ap| and
// |rp| must both be |num| words long. It returns the carry word of the
// operation. |ap| and |rp| may be equal but otherwise may not alias.
BN_ULONG GFp_bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, size_t num,
BN_ULONG w);
// |num| must be at least 4, at least on x86.
//
// In other forks, |bn_mul_mont| returns an |int| indicating whether it
@ -200,7 +194,7 @@ OPENSSL_COMPILE_ASSERT(sizeof(int) == sizeof(size_t) ||
int_and_size_t_abi_mismatch);
void GFp_bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, size_t num);
int GFp_bn_mul_mont_check_top(int top);
int GFp_bn_mul_mont_check_num_limbs(size_t top);
static inline void bn_umult_lohi(BN_ULONG *low_out, BN_ULONG *high_out,
BN_ULONG a, BN_ULONG b) {

View File

@ -199,48 +199,10 @@ int GFp_BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BIGNUM *n,
return 1;
}
int GFp_bn_mul_mont_check_top(int top) {
int GFp_bn_mul_mont_check_num_limbs(size_t num_limbs) {
// GFp_bn_mul_mont requires at least four limbs, at least for x86.
if (top < 4) {
if (num_limbs < 4) {
return 0;
}
return 1;
}
// Assumes a < n and b < n
int GFp_BN_mod_mul_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
const BIGNUM *n,
const BN_ULONG n0[BN_MONT_CTX_N0_LIMBS]) {
int num = n->top;
if (!GFp_bn_mul_mont_check_top(num)) {
return 0;
}
if (a->top == num && b->top == num) {
if (!GFp_bn_wexpand(r, num)) {
return 0;
}
GFp_bn_mul_mont(r->d, a->d, b->d, n->d, n0, num);
r->top = num;
GFp_bn_correct_top(r);
return 1;
}
BIGNUM tmp;
GFp_BN_init(&tmp);
int ret = 0;
if (!GFp_BN_mul_no_alias(&tmp, a, b) ||
!GFp_BN_from_montgomery_word(r, &tmp, n, n0)) {
goto err;
}
ret = 1;
err:
GFp_BN_free(&tmp);
return ret;
}

View File

@ -1,135 +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.] */
#include <GFp/bn.h>
#include <assert.h>
#include <string.h>
#include "internal.h"
static void GFp_bn_mul_normal(BN_ULONG *r, const BN_ULONG *a, size_t na,
const BN_ULONG *b, size_t nb) {
assert(r != a);
assert(r != b);
if (na < nb) {
size_t itmp = na;
na = nb;
nb = itmp;
const BN_ULONG *ltmp = a;
a = b;
b = ltmp;
}
BN_ULONG *rr = &(r[na]);
if (nb == 0) {
memset(r, 0, na * sizeof(BN_ULONG));
return;
}
rr[0] = GFp_bn_mul_words(r, a, na, b[0]);
for (;;) {
if (--nb == 0) {
return;
}
rr[1] = GFp_bn_mul_add_words(&(r[1]), a, na, b[1]);
if (--nb == 0) {
return;
}
rr[2] = GFp_bn_mul_add_words(&(r[2]), a, na, b[2]);
if (--nb == 0) {
return;
}
rr[3] = GFp_bn_mul_add_words(&(r[3]), a, na, b[3]);
if (--nb == 0) {
return;
}
rr[4] = GFp_bn_mul_add_words(&(r[4]), a, na, b[4]);
rr += 4;
r += 4;
b += 4;
}
}
int GFp_BN_mul_no_alias(BIGNUM *r, const BIGNUM *a, const BIGNUM *b) {
assert(r != a);
assert(r != b);
int ret = 0;
int top, al, bl;
al = a->top;
bl = b->top;
if ((al == 0) || (bl == 0)) {
GFp_BN_zero(r);
return 1;
}
top = al + bl;
if (!GFp_bn_wexpand(r, top)) {
goto err;
}
r->top = top;
GFp_bn_mul_normal(r->d, a->d, al, b->d, bl);
GFp_bn_correct_top(r);
ret = 1;
err:
return ret;
}

View File

@ -154,24 +154,11 @@ extern "C" {
// Allocation and freeing.
// GFp_BN_init initialises a stack allocated |BIGNUM|.
OPENSSL_EXPORT void GFp_BN_init(BIGNUM *bn);
// GFp_BN_free frees the data referenced by |bn| and, if |bn| was originally
// allocated on the heap, frees |bn| also.
OPENSSL_EXPORT void GFp_BN_free(BIGNUM *bn);
// GFp_BN_copy sets |dest| equal to |src| and returns one on success or zero on
// failure.
OPENSSL_EXPORT int GFp_BN_copy(BIGNUM *dest, const BIGNUM *src);
// Basic functions.
// GFp_BN_zero sets |bn| to zero.
OPENSSL_EXPORT void GFp_BN_zero(BIGNUM *bn);
// Internal functions.
//
// These functions are useful for code that is doing low-level manipulations of
@ -188,13 +175,6 @@ OPENSSL_EXPORT void GFp_bn_correct_top(BIGNUM *bn);
OPENSSL_EXPORT int GFp_bn_wexpand(BIGNUM *bn, size_t words);
// Simple arithmetic
// GFp_BN_mul_no_alias sets |r| = |a| * |b|, where |r| must not be the same pointer
// as |a| or |b|. Returns one on success and zero otherwise.
OPENSSL_EXPORT int GFp_BN_mul_no_alias(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
// Modulo arithmetic.
// GFp_BN_mod_mul_mont set |r| equal to |a| * |b|, in the Montgomery domain.

View File

@ -38,6 +38,7 @@
//! [Static checking of units in Servo]:
//! https://blog.mozilla.org/research/2014/06/23/static-checking-of-units-in-servo/
#![allow(box_pointers)]
use {bits, bssl, c, error, limb, untrusted};
use arithmetic::montgomery::*;
@ -389,17 +390,39 @@ impl<AF, BF, M> ModMul<Elem<M, BF>, M> for Elem<M, AF>
}
}
pub fn elem_mul<M, AF, BF>(a: &Elem<M, AF>, b: Elem<M, BF>, m: &Modulus<M>)
pub fn elem_mul<M, AF, BF>(a: &Elem<M, AF>, mut b: Elem<M, BF>, m: &Modulus<M>)
-> Result<Elem<M, <(AF, BF) as ProductEncoding>::Output>,
error::Unspecified>
where (AF, BF): ProductEncoding {
let mut r = b.value;
let m_limbs = (m.value.0).0.limbs();
let num_limbs = m_limbs.len();
bssl::map_result(unsafe {
GFp_BN_mod_mul_mont(&mut r.0, a.value.as_ref(), &r.0, &m.value.as_ref(),
&m.n0)
GFp_bn_mul_mont_check_num_limbs(num_limbs)
})?;
let mut a_limbs;
let a_limbs = if a.value.limbs().len() == num_limbs {
a.value.limbs()
} else {
assert!(a.value.limbs().len() < num_limbs);
a_limbs = vec![0; num_limbs];
a_limbs[..a.value.limbs().len()].copy_from_slice(a.value.limbs());
&a_limbs
};
b.value.0.make_limbs(num_limbs, |b_limbs| {
assert_eq!(a_limbs.len(), num_limbs);
assert_eq!(b_limbs.len(), num_limbs);
unsafe {
GFp_bn_mul_mont(b_limbs.as_mut_ptr(), a_limbs.as_ptr(),
b_limbs.as_ptr(), m_limbs.as_ptr(), &m.n0,
num_limbs)
}
Ok(())
})?;
Ok(Elem {
value: r,
value: b.value,
m: PhantomData,
encoding: PhantomData,
})
@ -412,9 +435,42 @@ pub fn elem_set_to_product<M, AF, BF>(
a: &Elem<M, AF>, b: &Elem<M, BF>, m: &Modulus<M>)
-> Result<(), error::Unspecified>
where (AF, BF): ProductEncoding {
let m_limbs = (m.value.0).0.limbs();
let num_limbs = m_limbs.len();
bssl::map_result(unsafe {
GFp_BN_mod_mul_mont(r.value.as_mut_ref(), a.value.as_ref(),
b.value.as_ref(), &m.value.as_ref(), &m.n0)
GFp_bn_mul_mont_check_num_limbs(num_limbs)
})?;
let mut a_limbs;
let a_limbs = if a.value.limbs().len() == num_limbs {
a.value.limbs()
} else {
assert!(a.value.limbs().len() < num_limbs);
a_limbs = vec![0; num_limbs];
a_limbs[..a.value.limbs().len()].copy_from_slice(a.value.limbs());
&a_limbs
};
let mut b_limbs;
let b_limbs = if b.value.limbs().len() == num_limbs {
b.value.limbs()
} else {
assert!(b.value.limbs().len() < num_limbs);
b_limbs = vec![0; num_limbs];
b_limbs[..b.value.limbs().len()].copy_from_slice(b.value.limbs());
&b_limbs
};
r.value.0.make_limbs(num_limbs, |r_limbs| {
assert_eq!(r_limbs.len(), num_limbs);
assert_eq!(a_limbs.len(), num_limbs);
assert_eq!(b_limbs.len(), num_limbs);
unsafe {
GFp_bn_mul_mont(r_limbs.as_mut_ptr(), a_limbs.as_ptr(),
b_limbs.as_ptr(), m_limbs.as_ptr(), &m.n0,
num_limbs)
}
Ok(())
})
}
@ -462,13 +518,19 @@ pub fn elem_squared<M, E>(a: Elem<M, E>, m: &Modulus<M>)
-> Result<Elem<M, <(E, E) as ProductEncoding>::Output>,
error::Unspecified>
where (E, E): ProductEncoding {
let m_limbs = (m.value.0).0.limbs();
let num_limbs = m_limbs.len();
let mut value = a.value;
bssl::map_result(unsafe {
GFp_BN_mod_mul_mont(value.as_mut_ref(), value.as_ref(), value.as_ref(),
&m.value.as_ref(), &m.n0)
value.0.make_limbs(num_limbs, |limbs| {
assert_eq!(limbs.len(), num_limbs);
unsafe {
GFp_bn_mul_mont(limbs.as_mut_ptr(), limbs.as_ptr(), limbs.as_ptr(),
m_limbs.as_ptr(), &m.n0, num_limbs)
}
Ok(())
})?;
Ok(Elem {
value: value,
value,
m: PhantomData,
encoding: PhantomData,
})
@ -1203,8 +1265,10 @@ pub use self::repr_c::BIGNUM;
extern {
// `r` and/or 'a' and/or 'b' may alias.
fn GFp_BN_mod_mul_mont(r: *mut BIGNUM, a: *const BIGNUM, b: *const BIGNUM,
n: &BIGNUM, n0: &N0) -> c::int;
fn GFp_bn_mul_mont(r: *mut limb::Limb, a: *const limb::Limb,
b: *const limb::Limb, n: *const limb::Limb,
n0: &N0, num_limbs: c::size_t);
fn GFp_bn_mul_mont_check_num_limbs(num_limbs: c::size_t) -> c::int;
// The use of references here implies lack of aliasing.
fn GFp_BN_copy(a: &mut BIGNUM, b: &BIGNUM) -> c::int;