Remove now-unused BIGNUM functions, and bn_test.cc (the last C++ use).
These functions can be removed thanks to the new modular inversion implementation.
This commit is contained in:
parent
e46b485c09
commit
efdffc91db
14
Cargo.toml
14
Cargo.toml
@ -148,11 +148,8 @@ include = [
|
||||
"crypto/bn/asm/x86_64-mont.pl",
|
||||
"crypto/bn/asm/x86_64-mont5.pl",
|
||||
"crypto/bn/bn.c",
|
||||
"crypto/bn/bn_test.cc",
|
||||
"crypto/bn/bn_tests.txt",
|
||||
"crypto/bn/cmp.c",
|
||||
"crypto/bn/convert.c",
|
||||
"crypto/bn/ctx.c",
|
||||
"crypto/bn/div.c",
|
||||
"crypto/bn/exponentiation.c",
|
||||
"crypto/bn/gcd.c",
|
||||
@ -227,14 +224,6 @@ include = [
|
||||
"crypto/sha/asm/sha512-armv4.pl",
|
||||
"crypto/sha/asm/sha512-armv8.pl",
|
||||
"crypto/sha/asm/sha512-x86_64.pl",
|
||||
"crypto/test/bn_test_convert.c",
|
||||
"crypto/test/bn_test_lib.c",
|
||||
"crypto/test/bn_test_lib.h",
|
||||
"crypto/test/bn_test_new.c",
|
||||
"crypto/test/bn_test_util.h",
|
||||
"crypto/test/file_test.cc",
|
||||
"crypto/test/file_test.h",
|
||||
"crypto/test/scoped_types.h",
|
||||
"include/GFp/aes.h",
|
||||
"include/GFp/arm_arch.h",
|
||||
"include/GFp/base.h",
|
||||
@ -287,11 +276,10 @@ rayon = "0.7"
|
||||
default = ["use_heap", "dev_urandom_fallback"]
|
||||
dev_urandom_fallback = []
|
||||
internal_benches = []
|
||||
rsa_signing = ["bn_tests", "use_heap"]
|
||||
rsa_signing = ["use_heap"]
|
||||
slow_tests = []
|
||||
test_logging = []
|
||||
use_heap = []
|
||||
bn_tests = []
|
||||
|
||||
# XXX: debug = false because of https://github.com/rust-lang/rust/issues/34122
|
||||
|
||||
|
54
build.rs
54
build.rs
@ -89,7 +89,6 @@ const RING_SRCS: &'static [(&'static [&'static str], &'static str)] = &[
|
||||
(&[], "crypto/bn/convert.c"),
|
||||
(&[], "crypto/bn/div.c"),
|
||||
(&[], "crypto/bn/exponentiation.c"),
|
||||
(&[], "crypto/bn/gcd.c"),
|
||||
(&[], "crypto/bn/generic.c"),
|
||||
(&[], "crypto/bn/montgomery.c"),
|
||||
(&[], "crypto/bn/montgomery_inv.c"),
|
||||
@ -168,11 +167,7 @@ const SHA256_ARMV8: &'static str = "crypto/sha/asm/sha256-armv8.pl";
|
||||
const SHA512_ARMV8: &'static str = "crypto/sha/asm/sha512-armv8.pl";
|
||||
|
||||
const RING_TEST_SRCS: &'static [&'static str] = &[
|
||||
("crypto/bn/bn_test.cc"),
|
||||
("crypto/constant_time_test.c"),
|
||||
("crypto/test/bn_test_convert.c"),
|
||||
("crypto/test/bn_test_new.c"),
|
||||
("crypto/test/file_test.cc"),
|
||||
];
|
||||
|
||||
#[cfg_attr(rustfmt, rustfmt_skip)]
|
||||
@ -189,10 +184,6 @@ const RING_INCLUDES: &'static [&'static str] =
|
||||
"crypto/limbs/limbs.h",
|
||||
"crypto/limbs/limbs.inl",
|
||||
"crypto/modes/internal.h",
|
||||
"crypto/test/bn_test_lib.h",
|
||||
"crypto/test/bn_test_util.h",
|
||||
"crypto/test/file_test.h",
|
||||
"crypto/test/scoped_types.h",
|
||||
"include/GFp/aes.h",
|
||||
"include/GFp/arm_arch.h",
|
||||
"include/GFp/base.h",
|
||||
@ -229,17 +220,6 @@ fn c_flags(target: &Target) -> &'static [&'static str] {
|
||||
}
|
||||
}
|
||||
|
||||
fn cxx_flags(target: &Target) -> &'static [&'static str] {
|
||||
if target.env != MSVC {
|
||||
static NON_MSVC_FLAGS: &'static [&'static str] = &[
|
||||
"-std=c++0x" // GCC 4.6 requires "c++0x" instead of "c++11"
|
||||
];
|
||||
NON_MSVC_FLAGS
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
}
|
||||
|
||||
fn cpp_flags(target: &Target) -> &'static [&'static str] {
|
||||
if target.env != MSVC {
|
||||
static NON_MSVC_FLAGS: &'static [&'static str] = &[
|
||||
@ -482,14 +462,6 @@ fn build_c_code(target: &Target, pregenerated: PathBuf, out_dir: &Path) {
|
||||
|
||||
let test_srcs = RING_TEST_SRCS.iter()
|
||||
.map(PathBuf::from)
|
||||
// Allow the C++-based tests to be disabled
|
||||
.filter(|p| cfg!(feature = "bn_tests") ||
|
||||
p.extension().unwrap().to_str().unwrap() != "cc")
|
||||
// Avoid the libstdc++ vs libc++ issue for macOS/iOS, and g++ issue on
|
||||
// musl by just avoiding all the C++-based tests.
|
||||
.filter(|p| !(target.os() == "macos" || target.os == "ios" ||
|
||||
target.env() == "musl") ||
|
||||
p.extension().unwrap().to_str().unwrap() != "cc")
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let libs = [
|
||||
@ -505,18 +477,6 @@ fn build_c_code(target: &Target, pregenerated: PathBuf, out_dir: &Path) {
|
||||
build_library(&target, &out_dir, lib_name, srcs, additional_srcs,
|
||||
includes_modified));
|
||||
|
||||
if target.env() != "msvc" &&
|
||||
target.env() != "musl" &&
|
||||
cfg!(feature = "bn_tests") &&
|
||||
!(target.os() == "macos" || target.os() == "ios") {
|
||||
let libcxx = if use_libcxx(target) {
|
||||
"c++"
|
||||
} else {
|
||||
"stdc++"
|
||||
};
|
||||
println!("cargo:rustc-flags=-l dylib={}", libcxx);
|
||||
}
|
||||
|
||||
println!("cargo:rustc-link-search=native={}",
|
||||
out_dir.to_str().expect("Invalid path"));
|
||||
}
|
||||
@ -613,15 +573,6 @@ fn cc(file: &Path, ext: &str, target: &Target, out_dir: &Path) -> Command {
|
||||
let _ = c.flag(f);
|
||||
}
|
||||
},
|
||||
"cc" => {
|
||||
for f in cxx_flags(target) {
|
||||
let _ = c.flag(f);
|
||||
}
|
||||
let _ = c.cpp(true);
|
||||
if use_libcxx(target) {
|
||||
let _ = c.cpp_set_stdlib(Some("c++"));
|
||||
}
|
||||
},
|
||||
"S" => {},
|
||||
e => panic!("Unsupported file extension: {:?}", e),
|
||||
};
|
||||
@ -696,10 +647,6 @@ fn yasm(file: &Path, arch: &str, out_file: &Path) -> Command {
|
||||
c
|
||||
}
|
||||
|
||||
fn use_libcxx(target: &Target) -> bool {
|
||||
target.os() == "freebsd"
|
||||
}
|
||||
|
||||
fn run_command_with_args<S>(command_name: S, args: &[String])
|
||||
where S: AsRef<std::ffi::OsStr> + Copy
|
||||
{
|
||||
@ -835,7 +782,6 @@ fn is_tracked(file: &DirEntry) {
|
||||
RING_INCLUDES.iter().any(cmp)
|
||||
},
|
||||
Some("c") |
|
||||
Some("cc") |
|
||||
Some("S") |
|
||||
Some("asm") => {
|
||||
RING_SRCS.iter().any(|&(_, ref f)| cmp(f)) ||
|
||||
|
@ -1,558 +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 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the Eric Young open source
|
||||
* license provided above.
|
||||
*
|
||||
* The binary polynomial arithmetic software is originally written by
|
||||
* Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
|
||||
* Laboratories. */
|
||||
|
||||
/* Per C99, various stdint.h and inttypes.h macros (the latter used by bn.h) are
|
||||
* unavailable in C++ unless some macros are defined. C++11 overruled this
|
||||
* decision, but older Android NDKs still require it. */
|
||||
#if !defined(__STDC_FORMAT_MACROS)
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <GFp/bn.h>
|
||||
#include <GFp/err.h>
|
||||
#include <GFp/mem.h>
|
||||
|
||||
#include "../test/bn_test_lib.h"
|
||||
#include "../crypto/test/file_test.h"
|
||||
#include "../crypto/test/scoped_types.h"
|
||||
#include "../test/bn_test_util.h"
|
||||
|
||||
|
||||
/* Prototypes to avoid -Wmissing-prototypes warnings. */
|
||||
extern "C" int bssl_bn_test_main(void);
|
||||
|
||||
|
||||
static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
|
||||
BIGNUM *raw = NULL;
|
||||
int ret = GFp_BN_hex2bn(&raw, in);
|
||||
out->reset(raw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ScopedBIGNUM GetBIGNUM(FileTest *t, const char *attribute) {
|
||||
std::string hex;
|
||||
if (!t->GetAttribute(&hex, attribute)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ScopedBIGNUM ret;
|
||||
if (HexToBIGNUM(&ret, hex.c_str()) != static_cast<int>(hex.size())) {
|
||||
t->PrintLine("Could not decode '", hex.c_str(), "'.");
|
||||
return nullptr;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool GetInt(FileTest *t, int *out, const char *attribute) {
|
||||
ScopedBIGNUM ret = GetBIGNUM(t, attribute);
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// This is |BN_get_word|, inlined and improved.
|
||||
switch (ret->top) {
|
||||
case 0:
|
||||
*out = 0;
|
||||
return 1;
|
||||
case 1:
|
||||
if (ret->d[0] > (BN_ULONG)INT_MAX) {
|
||||
return false;
|
||||
}
|
||||
*out = static_cast<int>(ret->d[0]);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ExpectBIGNUMsEqual(FileTest *t, const char *operation,
|
||||
const BIGNUM *expected, const BIGNUM *actual) {
|
||||
if (GFp_BN_cmp(expected, actual) == 0) {
|
||||
return true;
|
||||
}
|
||||
t->PrintLine("Got wrong value for ", operation);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool TestSum(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM b = GetBIGNUM(t, "B");
|
||||
ScopedBIGNUM sum = GetBIGNUM(t, "Sum");
|
||||
if (!a || !b || !sum) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new());
|
||||
if (!ret ||
|
||||
!GFp_BN_add(ret.get(), a.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A + B", sum.get(), ret.get()) ||
|
||||
!GFp_BN_sub(ret.get(), sum.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum - A", b.get(), ret.get()) ||
|
||||
!GFp_BN_sub(ret.get(), sum.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum - B", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test that the functions work when |r| and |a| point to the same |BIGNUM|,
|
||||
// or when |r| and |b| point to the same |BIGNUM|. TODO: Test the case where
|
||||
// all of |r|, |a|, and |b| point to the same |BIGNUM|.
|
||||
if (!GFp_BN_copy(ret.get(), a.get()) ||
|
||||
!GFp_BN_add(ret.get(), ret.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A + B (r is a)", sum.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), b.get()) ||
|
||||
!GFp_BN_add(ret.get(), a.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A + B (r is b)", sum.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), sum.get()) ||
|
||||
!GFp_BN_sub(ret.get(), ret.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum - A (r is a)", b.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), a.get()) ||
|
||||
!GFp_BN_sub(ret.get(), sum.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum - A (r is b)", b.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), sum.get()) ||
|
||||
!GFp_BN_sub(ret.get(), ret.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum - B (r is a)", a.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), b.get()) ||
|
||||
!GFp_BN_sub(ret.get(), sum.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum - B (r is b)", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test |GFp_BN_uadd| and |GFp_BN_usub| with the prerequisites they are
|
||||
// documented as having. Note that these functions are frequently used when
|
||||
// the prerequisites don't hold. In those cases, they are supposed to work as
|
||||
// if the prerequisite hold, but we don't test that yet. TODO: test that.
|
||||
if (!GFp_BN_is_negative(a.get()) &&
|
||||
!GFp_BN_is_negative(b.get()) && GFp_BN_cmp(a.get(), b.get()) >= 0) {
|
||||
if (!GFp_BN_uadd(ret.get(), a.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A +u B", sum.get(), ret.get()) ||
|
||||
!GFp_BN_usub(ret.get(), sum.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum -u A", b.get(), ret.get()) ||
|
||||
!GFp_BN_usub(ret.get(), sum.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum -u B", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test that the functions work when |r| and |a| point to the same |BIGNUM|,
|
||||
// or when |r| and |b| point to the same |BIGNUM|. TODO: Test the case where
|
||||
// all of |r|, |a|, and |b| point to the same |BIGNUM|.
|
||||
if (!GFp_BN_copy(ret.get(), a.get()) ||
|
||||
!GFp_BN_uadd(ret.get(), ret.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A +u B (r is a)", sum.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), b.get()) ||
|
||||
!GFp_BN_uadd(ret.get(), a.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A +u B (r is b)", sum.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), sum.get()) ||
|
||||
!GFp_BN_usub(ret.get(), ret.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum -u A (r is a)", b.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), a.get()) ||
|
||||
!GFp_BN_usub(ret.get(), sum.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum -u A (r is b)", b.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), sum.get()) ||
|
||||
!GFp_BN_usub(ret.get(), ret.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum -u B (r is a)", a.get(), ret.get()) ||
|
||||
!GFp_BN_copy(ret.get(), b.get()) ||
|
||||
!GFp_BN_usub(ret.get(), sum.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Sum -u B (r is b)", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestLShift1(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM lshift1 = GetBIGNUM(t, "LShift1");
|
||||
ScopedBIGNUM zero(GFp_BN_new());
|
||||
if (!a || !lshift1 || !zero) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GFp_BN_zero(zero.get());
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new()), two(GFp_BN_new()), remainder(GFp_BN_new());
|
||||
if (!ret || !two || !remainder ||
|
||||
!GFp_BN_set_word(two.get(), 2) ||
|
||||
!GFp_BN_add(ret.get(), a.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A + A", lshift1.get(), ret.get()) ||
|
||||
!GFp_BN_mul_no_alias(ret.get(), a.get(), two.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A * 2", lshift1.get(), ret.get()) ||
|
||||
!GFp_BN_div(ret.get(), remainder.get(), lshift1.get(), two.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "LShift1 / 2", a.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "LShift1 % 2", zero.get(), remainder.get()) ||
|
||||
!GFp_BN_lshift(ret.get(), a.get(), 1) ||
|
||||
!ExpectBIGNUMsEqual(t, "A << 1", lshift1.get(), ret.get()) ||
|
||||
!GFp_BN_rshift1(ret.get(), lshift1.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "LShift >> 1", a.get(), ret.get()) ||
|
||||
!GFp_BN_rshift1(ret.get(), lshift1.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "LShift >> 1", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the LSB to 1 and test rshift1 again.
|
||||
if (!GFp_BN_set_bit(lshift1.get(), 0) ||
|
||||
!GFp_BN_div(ret.get(), nullptr /* rem */, lshift1.get(), two.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "(LShift1 | 1) / 2", a.get(), ret.get()) ||
|
||||
!GFp_BN_rshift1(ret.get(), lshift1.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "(LShift | 1) >> 1", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestLShift(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM lshift = GetBIGNUM(t, "LShift");
|
||||
int n = 0;
|
||||
if (!a || !lshift || !GetInt(t, &n, "N")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new());
|
||||
if (!ret ||
|
||||
!GFp_BN_lshift(ret.get(), a.get(), n) ||
|
||||
!ExpectBIGNUMsEqual(t, "A << N", lshift.get(), ret.get()) ||
|
||||
!GFp_BN_rshift(ret.get(), lshift.get(), n) ||
|
||||
!ExpectBIGNUMsEqual(t, "A >> N", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestRShift(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM rshift = GetBIGNUM(t, "RShift");
|
||||
int n = 0;
|
||||
if (!a || !rshift || !GetInt(t, &n, "N")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new());
|
||||
if (!ret ||
|
||||
!GFp_BN_rshift(ret.get(), a.get(), n) ||
|
||||
!ExpectBIGNUMsEqual(t, "A >> N", rshift.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestSquare(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM square = GetBIGNUM(t, "Square");
|
||||
ScopedBIGNUM zero(GFp_BN_new());
|
||||
if (!a || !square || !zero) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GFp_BN_zero(zero.get());
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new()), remainder(GFp_BN_new());
|
||||
if (!ret || !remainder ||
|
||||
!GFp_BN_mul_no_alias(ret.get(), a.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A * A", square.get(), ret.get()) ||
|
||||
!GFp_BN_div(ret.get(), remainder.get(), square.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Square / A", a.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Square % A", zero.get(), remainder.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestProduct(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM b = GetBIGNUM(t, "B");
|
||||
ScopedBIGNUM product = GetBIGNUM(t, "Product");
|
||||
ScopedBIGNUM zero(GFp_BN_new());
|
||||
if (!a || !b || !product || !zero) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GFp_BN_zero(zero.get());
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new()), remainder(GFp_BN_new());
|
||||
if (!ret || !remainder ||
|
||||
!GFp_BN_mul_no_alias(ret.get(), a.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A * B", product.get(), ret.get()) ||
|
||||
!GFp_BN_div(ret.get(), remainder.get(), product.get(), a.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Product / A", b.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Product % A", zero.get(), remainder.get()) ||
|
||||
!GFp_BN_div(ret.get(), remainder.get(), product.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Product / B", a.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Product % B", zero.get(), remainder.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestQuotient(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM b = GetBIGNUM(t, "B");
|
||||
ScopedBIGNUM quotient = GetBIGNUM(t, "Quotient");
|
||||
ScopedBIGNUM remainder = GetBIGNUM(t, "Remainder");
|
||||
if (!a || !b || !quotient || !remainder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new()), ret2(GFp_BN_new());
|
||||
if (!ret || !ret2 ||
|
||||
!GFp_BN_div(ret.get(), ret2.get(), a.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A / B", quotient.get(), ret.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A % B", remainder.get(), ret2.get()) ||
|
||||
!GFp_BN_mul_no_alias(ret.get(), quotient.get(), b.get()) ||
|
||||
!GFp_BN_add(ret.get(), ret.get(), remainder.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "Quotient * B + Remainder", a.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test GFp_BN_nnmod.
|
||||
if (!GFp_BN_is_negative(b.get())) {
|
||||
ScopedBIGNUM nnmod(GFp_BN_new());
|
||||
if (!nnmod ||
|
||||
!GFp_BN_copy(nnmod.get(), remainder.get()) ||
|
||||
(GFp_BN_is_negative(nnmod.get()) &&
|
||||
!GFp_BN_add(nnmod.get(), nnmod.get(), b.get())) ||
|
||||
!GFp_BN_nnmod(ret.get(), a.get(), b.get()) ||
|
||||
!ExpectBIGNUMsEqual(t, "A % B (non-negative)", nnmod.get(),
|
||||
ret.get())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestModInv(FileTest *t) {
|
||||
ScopedBIGNUM a = GetBIGNUM(t, "A");
|
||||
ScopedBIGNUM m = GetBIGNUM(t, "M");
|
||||
ScopedBIGNUM mod_inv = GetBIGNUM(t, "ModInv");
|
||||
if (!a || !m || !mod_inv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedBIGNUM ret(GFp_BN_new());
|
||||
int no_inverse;
|
||||
if (!ret ||
|
||||
!GFp_BN_mod_inverse_odd(ret.get(), &no_inverse, a.get(), m.get()) ||
|
||||
no_inverse ||
|
||||
!ExpectBIGNUMsEqual(t, "inv(A) (mod M)", mod_inv.get(), ret.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Test {
|
||||
const char *name;
|
||||
bool (*func)(FileTest *t);
|
||||
};
|
||||
|
||||
static const Test kTests[] = {
|
||||
{"Sum", TestSum},
|
||||
{"LShift1", TestLShift1},
|
||||
{"LShift", TestLShift},
|
||||
{"RShift", TestRShift},
|
||||
{"Square", TestSquare},
|
||||
{"Product", TestProduct},
|
||||
{"Quotient", TestQuotient},
|
||||
{"ModInv", TestModInv},
|
||||
};
|
||||
|
||||
static bool RunTest(FileTest *t, void *) {
|
||||
for (const Test &test : kTests) {
|
||||
if (t->GetType() != test.name) {
|
||||
continue;
|
||||
}
|
||||
return test.func(t);
|
||||
}
|
||||
t->PrintLine("Unknown test type: ", t->GetType().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
static int BN_is_word(const BIGNUM *bn, BN_ULONG w) {
|
||||
return GFp_BN_abs_is_word(bn, w) && (w == 0 || bn->neg == 0);
|
||||
}
|
||||
|
||||
static bool TestHex2BN() {
|
||||
ScopedBIGNUM bn;
|
||||
int ret = HexToBIGNUM(&bn, "0");
|
||||
if (ret != 1 || !GFp_BN_is_zero(bn.get()) || GFp_BN_is_negative(bn.get())) {
|
||||
fprintf(stderr, "GFp_BN_hex2bn gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = HexToBIGNUM(&bn, "256");
|
||||
if (ret != 3 || !BN_is_word(bn.get(), 0x256) ||
|
||||
GFp_BN_is_negative(bn.get())) {
|
||||
fprintf(stderr, "GFp_BN_hex2bn gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = HexToBIGNUM(&bn, "-42");
|
||||
if (ret != 3 || !GFp_BN_abs_is_word(bn.get(), 0x42) ||
|
||||
!GFp_BN_is_negative(bn.get())) {
|
||||
fprintf(stderr, "GFp_BN_hex2bn gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = HexToBIGNUM(&bn, "-0");
|
||||
if (ret != 2 || !GFp_BN_is_zero(bn.get()) || GFp_BN_is_negative(bn.get())) {
|
||||
fprintf(stderr, "GFp_BN_hex2bn gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = HexToBIGNUM(&bn, "abctrailing garbage is ignored");
|
||||
if (ret != 3 || !BN_is_word(bn.get(), 0xabc) ||
|
||||
GFp_BN_is_negative(bn.get())) {
|
||||
fprintf(stderr, "GFp_BN_hex2bn gave a bad result.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestCmpWord() {
|
||||
static const BN_ULONG kMaxWord = (BN_ULONG)-1;
|
||||
|
||||
ScopedBIGNUM one(GFp_BN_new());
|
||||
ScopedBIGNUM r(GFp_BN_new());
|
||||
if (!one ||
|
||||
!GFp_BN_set_word(one.get(), 1) ||
|
||||
!r) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GFp_BN_set_word(r.get(), 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GFp_BN_cmp_word(r.get(), 0) != 0 ||
|
||||
GFp_BN_cmp_word(r.get(), 1) >= 0 ||
|
||||
GFp_BN_cmp_word(r.get(), kMaxWord) >= 0) {
|
||||
fprintf(stderr, "GFp_BN_cmp_word compared against 0 incorrectly.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GFp_BN_set_word(r.get(), 100)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GFp_BN_cmp_word(r.get(), 0) <= 0 ||
|
||||
GFp_BN_cmp_word(r.get(), 99) <= 0 ||
|
||||
GFp_BN_cmp_word(r.get(), 100) != 0 ||
|
||||
GFp_BN_cmp_word(r.get(), 101) >= 0 ||
|
||||
GFp_BN_cmp_word(r.get(), kMaxWord) >= 0) {
|
||||
fprintf(stderr, "GFp_BN_cmp_word compared against 100 incorrectly.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GFp_BN_set_word(r.get(), kMaxWord)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GFp_BN_cmp_word(r.get(), 0) <= 0 ||
|
||||
GFp_BN_cmp_word(r.get(), kMaxWord - 1) <= 0 ||
|
||||
GFp_BN_cmp_word(r.get(), kMaxWord) != 0) {
|
||||
fprintf(stderr, "GFp_BN_cmp_word compared against kMaxWord incorrectly.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GFp_BN_add(r.get(), r.get(), one.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GFp_BN_cmp_word(r.get(), 0) <= 0 ||
|
||||
GFp_BN_cmp_word(r.get(), kMaxWord) <= 0) {
|
||||
fprintf(stderr, "GFp_BN_cmp_word compared against kMaxWord + 1 incorrectly.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern "C" int bssl_bn_test_main() {
|
||||
if (!TestHex2BN() ||
|
||||
!TestCmpWord()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(RunTest, nullptr, "crypto/bn/bn_tests.txt");
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,237 +0,0 @@
|
||||
// Copyright (c) 2016, Google Inc.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type test struct {
|
||||
LineNumber int
|
||||
Type string
|
||||
Values map[string]*big.Int
|
||||
}
|
||||
|
||||
type testScanner struct {
|
||||
scanner *bufio.Scanner
|
||||
lineNo int
|
||||
err error
|
||||
test test
|
||||
}
|
||||
|
||||
func newTestScanner(r io.Reader) *testScanner {
|
||||
return &testScanner{scanner: bufio.NewScanner(r)}
|
||||
}
|
||||
|
||||
func (s *testScanner) scanLine() bool {
|
||||
if !s.scanner.Scan() {
|
||||
return false
|
||||
}
|
||||
s.lineNo++
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *testScanner) addAttribute(line string) (key string, ok bool) {
|
||||
fields := strings.SplitN(line, "=", 2)
|
||||
if len(fields) != 2 {
|
||||
s.setError(errors.New("invalid syntax"))
|
||||
return "", false
|
||||
}
|
||||
|
||||
key = strings.TrimSpace(fields[0])
|
||||
value := strings.TrimSpace(fields[1])
|
||||
|
||||
valueInt, ok := new(big.Int).SetString(value, 16)
|
||||
if !ok {
|
||||
s.setError(fmt.Errorf("could not parse %q", value))
|
||||
return "", false
|
||||
}
|
||||
if _, dup := s.test.Values[key]; dup {
|
||||
s.setError(fmt.Errorf("duplicate key %q", key))
|
||||
return "", false
|
||||
}
|
||||
s.test.Values[key] = valueInt
|
||||
return key, true
|
||||
}
|
||||
|
||||
func (s *testScanner) Scan() bool {
|
||||
s.test = test{
|
||||
Values: make(map[string]*big.Int),
|
||||
}
|
||||
|
||||
// Scan until the first attribute.
|
||||
for {
|
||||
if !s.scanLine() {
|
||||
return false
|
||||
}
|
||||
if len(s.scanner.Text()) != 0 && s.scanner.Text()[0] != '#' {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
var ok bool
|
||||
s.test.Type, ok = s.addAttribute(s.scanner.Text())
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
s.test.LineNumber = s.lineNo
|
||||
|
||||
for s.scanLine() {
|
||||
if len(s.scanner.Text()) == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
if s.scanner.Text()[0] == '#' {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := s.addAttribute(s.scanner.Text()); !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return s.scanner.Err() == nil
|
||||
}
|
||||
|
||||
func (s *testScanner) Test() test {
|
||||
return s.test
|
||||
}
|
||||
|
||||
func (s *testScanner) Err() error {
|
||||
if s.err != nil {
|
||||
return s.err
|
||||
}
|
||||
return s.scanner.Err()
|
||||
}
|
||||
|
||||
func (s *testScanner) setError(err error) {
|
||||
s.err = fmt.Errorf("line %d: %s", s.lineNo, err)
|
||||
}
|
||||
|
||||
func checkKeys(t test, keys ...string) bool {
|
||||
var foundErrors bool
|
||||
|
||||
for _, k := range keys {
|
||||
if _, ok := t.Values[k]; !ok {
|
||||
fmt.Fprintf(os.Stderr, "Line %d: missing key %q.\n", t.LineNumber, k)
|
||||
foundErrors = true
|
||||
}
|
||||
}
|
||||
|
||||
for k, _ := range t.Values {
|
||||
var found bool
|
||||
for _, k2 := range keys {
|
||||
if k == k2 {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
fmt.Fprintf(os.Stderr, "Line %d: unexpected key %q.\n", t.LineNumber, k)
|
||||
foundErrors = true
|
||||
}
|
||||
}
|
||||
|
||||
return !foundErrors
|
||||
}
|
||||
|
||||
func checkResult(t test, expr, key string, r *big.Int) {
|
||||
if t.Values[key].Cmp(r) != 0 {
|
||||
fmt.Fprintf(os.Stderr, "Line %d: %s did not match %s.\n\tGot %s\n", t.LineNumber, expr, key, r.Text(16))
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: %s bn_tests.txt\n", os.Args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
in, err := os.Open(os.Args[1])
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error opening %s: %s.\n", os.Args[0], err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
scanner := newTestScanner(in)
|
||||
for scanner.Scan() {
|
||||
test := scanner.Test()
|
||||
switch test.Type {
|
||||
case "Sum":
|
||||
if checkKeys(test, "A", "B", "Sum") {
|
||||
r := new(big.Int).Add(test.Values["A"], test.Values["B"])
|
||||
checkResult(test, "A + B", "Sum", r)
|
||||
}
|
||||
case "LShift1":
|
||||
if checkKeys(test, "A", "LShift1") {
|
||||
r := new(big.Int).Add(test.Values["A"], test.Values["A"])
|
||||
checkResult(test, "A + A", "LShift1", r)
|
||||
}
|
||||
case "LShift":
|
||||
if checkKeys(test, "A", "N", "LShift") {
|
||||
r := new(big.Int).Lsh(test.Values["A"], uint(test.Values["N"].Uint64()))
|
||||
checkResult(test, "A << N", "LShift", r)
|
||||
}
|
||||
case "RShift":
|
||||
if checkKeys(test, "A", "N", "RShift") {
|
||||
r := new(big.Int).Rsh(test.Values["A"], uint(test.Values["N"].Uint64()))
|
||||
checkResult(test, "A >> N", "RShift", r)
|
||||
}
|
||||
case "Square":
|
||||
if checkKeys(test, "A", "Square") {
|
||||
r := new(big.Int).Mul(test.Values["A"], test.Values["A"])
|
||||
checkResult(test, "A * A", "Square", r)
|
||||
}
|
||||
case "Product":
|
||||
if checkKeys(test, "A", "B", "Product") {
|
||||
r := new(big.Int).Mul(test.Values["A"], test.Values["B"])
|
||||
checkResult(test, "A * B", "Product", r)
|
||||
}
|
||||
case "Quotient":
|
||||
if checkKeys(test, "A", "B", "Quotient", "Remainder") {
|
||||
q, r := new(big.Int).QuoRem(test.Values["A"], test.Values["B"], new(big.Int))
|
||||
checkResult(test, "A / B", "Quotient", q)
|
||||
checkResult(test, "A % B", "Remainder", r)
|
||||
}
|
||||
case "ModMul":
|
||||
if checkKeys(test, "A", "B", "M", "ModMul") {
|
||||
r := new(big.Int).Mul(test.Values["A"], test.Values["B"])
|
||||
r = r.Mod(r, test.Values["M"])
|
||||
checkResult(test, "A * B (mod M)", "ModMul", r)
|
||||
}
|
||||
case "ModExp":
|
||||
if checkKeys(test, "A", "E", "M", "ModExp") {
|
||||
r := new(big.Int).Exp(test.Values["A"], test.Values["E"], test.Values["M"])
|
||||
checkResult(test, "A ^ E (mod M)", "ModExp", r)
|
||||
}
|
||||
case "ModInv":
|
||||
if checkKeys(test, "A", "M", "ModInv") {
|
||||
r := new(big.Int).ModInverse(test.Values["A"], test.Values["M"])
|
||||
checkResult(test, "A ^ -1 (mod M)", "ModInv", r)
|
||||
}
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Line %d: unknown test type %q.\n", test.LineNumber, test.Type)
|
||||
}
|
||||
}
|
||||
if scanner.Err() != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error reading tests: %s.\n", scanner.Err())
|
||||
}
|
||||
}
|
354
crypto/bn/div.c
354
crypto/bn/div.c
@ -56,360 +56,6 @@
|
||||
|
||||
#include <GFp/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <GFp/err.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#if !defined(BN_ULLONG)
|
||||
/* GFp_bn_div_words divides a double-width |h|,|l| by |d| and returns the
|
||||
* result, which must fit in a |BN_ULONG|. */
|
||||
static BN_ULONG GFp_bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
|
||||
BN_ULONG dh, dl, q, ret = 0, th, tl, t;
|
||||
int i, count = 2;
|
||||
|
||||
if (d == 0) {
|
||||
return BN_MASK2;
|
||||
}
|
||||
|
||||
i = GFp_BN_num_bits_word(d);
|
||||
assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
|
||||
|
||||
i = BN_BITS2 - i;
|
||||
if (h >= d) {
|
||||
h -= d;
|
||||
}
|
||||
|
||||
if (i) {
|
||||
d <<= i;
|
||||
h = (h << i) | (l >> (BN_BITS2 - i));
|
||||
l <<= i;
|
||||
}
|
||||
dh = (d & BN_MASK2h) >> BN_BITS4;
|
||||
dl = (d & BN_MASK2l);
|
||||
for (;;) {
|
||||
if ((h >> BN_BITS4) == dh) {
|
||||
q = BN_MASK2l;
|
||||
} else {
|
||||
q = h / dh;
|
||||
}
|
||||
|
||||
th = q * dh;
|
||||
tl = dl * q;
|
||||
for (;;) {
|
||||
t = h - th;
|
||||
if ((t & BN_MASK2h) ||
|
||||
((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
|
||||
break;
|
||||
}
|
||||
q--;
|
||||
th -= dh;
|
||||
tl -= dl;
|
||||
}
|
||||
t = (tl >> BN_BITS4);
|
||||
tl = (tl << BN_BITS4) & BN_MASK2h;
|
||||
th += t;
|
||||
|
||||
if (l < tl) {
|
||||
th++;
|
||||
}
|
||||
l -= tl;
|
||||
if (h < th) {
|
||||
h += d;
|
||||
q--;
|
||||
}
|
||||
h -= th;
|
||||
|
||||
if (--count == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = q << BN_BITS4;
|
||||
h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
|
||||
l = (l & BN_MASK2l) << BN_BITS4;
|
||||
}
|
||||
|
||||
ret |= q;
|
||||
return ret;
|
||||
}
|
||||
#endif /* !defined(BN_ULLONG) */
|
||||
|
||||
static inline void GFp_bn_div_rem_words(BN_ULONG *quotient_out,
|
||||
BN_ULONG *rem_out, BN_ULONG n0,
|
||||
BN_ULONG n1, BN_ULONG d0) {
|
||||
/* GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when
|
||||
* the |BN_ULLONG|-based C code is used.
|
||||
*
|
||||
* GCC bugs:
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897
|
||||
* * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668
|
||||
*
|
||||
* Clang bugs:
|
||||
* * https://llvm.org/bugs/show_bug.cgi?id=6397
|
||||
* * https://llvm.org/bugs/show_bug.cgi?id=12418
|
||||
*
|
||||
* These issues aren't specific to x86 and x86_64, so it might be worthwhile
|
||||
* to add more assembly language implementations. */
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__)
|
||||
__asm__ volatile (
|
||||
"divl %4"
|
||||
: "=a"(*quotient_out), "=d"(*rem_out)
|
||||
: "a"(n1), "d"(n0), "rm"(d0)
|
||||
: "cc" );
|
||||
#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
|
||||
__asm__ volatile (
|
||||
"divq %4"
|
||||
: "=a"(*quotient_out), "=d"(*rem_out)
|
||||
: "a"(n1), "d"(n0), "rm"(d0)
|
||||
: "cc" );
|
||||
#else
|
||||
#if defined(BN_ULLONG)
|
||||
BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
|
||||
*quotient_out = (BN_ULONG)(n / d0);
|
||||
#else
|
||||
*quotient_out = GFp_bn_div_words(n0, n1, d0);
|
||||
#endif
|
||||
*rem_out = n1 - (*quotient_out * d0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* GFp_BN_div computes dv := num / divisor, rounding towards zero, and sets
|
||||
* up rm such that dv*divisor + rm = num holds.
|
||||
*
|
||||
* Thus:
|
||||
* dv->neg == num->neg ^ divisor->neg (unless the result is zero)
|
||||
* rm->neg == num->neg (unless the remainder is zero)
|
||||
* If 'dv' or 'rm' is NULL, the respective value is not returned.
|
||||
*
|
||||
* This was specifically designed to contain fewer branches that may leak
|
||||
* sensitive information; see "New Branch Prediction Vulnerabilities in OpenSSL
|
||||
* and Necessary Software Countermeasures" by Onur Acıçmez, Shay Gueron, and
|
||||
* Jean-Pierre Seifert. */
|
||||
int GFp_BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
|
||||
const BIGNUM *divisor) {
|
||||
int norm_shift, i, loop;
|
||||
BN_ULONG *resp, *wnump;
|
||||
BN_ULONG d0, d1;
|
||||
int num_n, div_n;
|
||||
|
||||
/* Invalid zero-padding would have particularly bad consequences
|
||||
* so don't just rely on bn_check_top() here */
|
||||
if ((num->top > 0 && num->d[num->top - 1] == 0) ||
|
||||
(divisor->top > 0 && divisor->d[divisor->top - 1] == 0)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GFp_BN_is_zero(divisor)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIGNUM snum;
|
||||
GFp_BN_init(&snum);
|
||||
|
||||
BIGNUM sdiv;
|
||||
GFp_BN_init(&sdiv);
|
||||
|
||||
BIGNUM tmp;
|
||||
GFp_BN_init(&tmp);
|
||||
|
||||
BIGNUM res_tmp;
|
||||
GFp_BN_init(&res_tmp);
|
||||
|
||||
BIGNUM wnum; /* Weak; do not |GFp_BN_free|. */
|
||||
|
||||
BIGNUM *res; /* weak pointer */
|
||||
if (dv == NULL) {
|
||||
res = &res_tmp;
|
||||
} else {
|
||||
res = dv;
|
||||
}
|
||||
|
||||
int ret = 0;
|
||||
|
||||
/* First we normalise the numbers */
|
||||
norm_shift = BN_BITS2 - ((GFp_BN_num_bits(divisor)) % BN_BITS2);
|
||||
if (!(GFp_BN_lshift(&sdiv, divisor, norm_shift))) {
|
||||
goto err;
|
||||
}
|
||||
sdiv.neg = 0;
|
||||
norm_shift += BN_BITS2;
|
||||
if (!(GFp_BN_lshift(&snum, num, norm_shift))) {
|
||||
goto err;
|
||||
}
|
||||
snum.neg = 0;
|
||||
|
||||
/* Since we don't want to have special-case logic for the case where snum is
|
||||
* larger than sdiv, we pad snum with enough zeroes without changing its
|
||||
* value. */
|
||||
if (snum.top <= sdiv.top + 1) {
|
||||
if (!GFp_bn_wexpand(&snum, sdiv.top + 2)) {
|
||||
goto err;
|
||||
}
|
||||
for (i = snum.top; i < sdiv.top + 2; i++) {
|
||||
snum.d[i] = 0;
|
||||
}
|
||||
snum.top = sdiv.top + 2;
|
||||
} else {
|
||||
if (!GFp_bn_wexpand(&snum, snum.top + 1)) {
|
||||
goto err;
|
||||
}
|
||||
snum.d[snum.top] = 0;
|
||||
snum.top++;
|
||||
}
|
||||
|
||||
div_n = sdiv.top;
|
||||
num_n = snum.top;
|
||||
loop = num_n - div_n;
|
||||
/* Lets setup a 'window' into snum
|
||||
* This is the part that corresponds to the current
|
||||
* 'area' being divided */
|
||||
|
||||
wnum.neg = 0;
|
||||
wnum.d = &(snum.d[loop]);
|
||||
wnum.top = div_n;
|
||||
/* only needed when |GFp_BN_ucmp| messes up the values between top and max */
|
||||
wnum.dmax = snum.dmax - loop; /* so we don't step out of bounds */
|
||||
|
||||
/* Get the top 2 words of sdiv */
|
||||
/* div_n=sdiv.top; */
|
||||
d0 = sdiv.d[div_n - 1];
|
||||
d1 = (div_n == 1) ? 0 : sdiv.d[div_n - 2];
|
||||
|
||||
/* pointer to the 'top' of snum */
|
||||
wnump = &(snum.d[num_n - 1]);
|
||||
|
||||
/* Setup to 'res' */
|
||||
res->neg = (num->neg ^ divisor->neg);
|
||||
if (!GFp_bn_wexpand(res, (loop + 1))) {
|
||||
goto err;
|
||||
}
|
||||
res->top = loop - 1;
|
||||
resp = &(res->d[loop - 1]);
|
||||
|
||||
/* space for temp */
|
||||
if (!GFp_bn_wexpand(&tmp, (div_n + 1))) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* if res->top == 0 then clear the neg value otherwise decrease
|
||||
* the resp pointer */
|
||||
if (res->top == 0) {
|
||||
res->neg = 0;
|
||||
} else {
|
||||
resp--;
|
||||
}
|
||||
|
||||
for (i = 0; i < loop - 1; i++, wnump--, resp--) {
|
||||
BN_ULONG q, l0;
|
||||
/* the first part of the loop uses the top two words of snum and sdiv to
|
||||
* calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv */
|
||||
BN_ULONG n0, n1, rem = 0;
|
||||
|
||||
n0 = wnump[0];
|
||||
n1 = wnump[-1];
|
||||
if (n0 == d0) {
|
||||
q = BN_MASK2;
|
||||
} else {
|
||||
/* n0 < d0 */
|
||||
GFp_bn_div_rem_words(&q, &rem, n0, n1, d0);
|
||||
|
||||
#ifdef BN_ULLONG
|
||||
BN_ULLONG t2 = (BN_ULLONG)d1 * q;
|
||||
for (;;) {
|
||||
if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) {
|
||||
break;
|
||||
}
|
||||
q--;
|
||||
rem += d0;
|
||||
if (rem < d0) {
|
||||
break; /* don't let rem overflow */
|
||||
}
|
||||
t2 -= d1;
|
||||
}
|
||||
#else /* !BN_ULLONG */
|
||||
BN_ULONG t2l, t2h;
|
||||
bn_umult_lohi(&t2l, &t2h, d1, q);
|
||||
for (;;) {
|
||||
if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) {
|
||||
break;
|
||||
}
|
||||
q--;
|
||||
rem += d0;
|
||||
if (rem < d0) {
|
||||
break; /* don't let rem overflow */
|
||||
}
|
||||
if (t2l < d1) {
|
||||
t2h--;
|
||||
}
|
||||
t2l -= d1;
|
||||
}
|
||||
#endif /* !BN_ULLONG */
|
||||
}
|
||||
|
||||
l0 = GFp_bn_mul_words(tmp.d, sdiv.d, div_n, q);
|
||||
tmp.d[div_n] = l0;
|
||||
wnum.d--;
|
||||
/* ingore top values of the bignums just sub the two
|
||||
* BN_ULONG arrays with GFp_bn_sub_words */
|
||||
if (GFp_bn_sub_words(wnum.d, wnum.d, tmp.d, div_n + 1)) {
|
||||
/* Note: As we have considered only the leading
|
||||
* two BN_ULONGs in the calculation of q, sdiv * q
|
||||
* might be greater than wnum (but then (q-1) * sdiv
|
||||
* is less or equal than wnum)
|
||||
*/
|
||||
q--;
|
||||
if (GFp_bn_add_words(wnum.d, wnum.d, sdiv.d, div_n)) {
|
||||
/* we can't have an overflow here (assuming
|
||||
* that q != 0, but if q == 0 then tmp is
|
||||
* zero anyway) */
|
||||
(*wnump)++;
|
||||
}
|
||||
}
|
||||
/* store part of the result */
|
||||
*resp = q;
|
||||
}
|
||||
GFp_bn_correct_top(&snum);
|
||||
if (rm != NULL) {
|
||||
/* Keep a copy of the neg flag in num because if rm==num |GFp_BN_rshift|
|
||||
* will overwrite it. */
|
||||
int neg = num->neg;
|
||||
if (!GFp_BN_rshift(rm, &snum, norm_shift)) {
|
||||
goto err;
|
||||
}
|
||||
if (!GFp_BN_is_zero(rm)) {
|
||||
rm->neg = neg;
|
||||
}
|
||||
}
|
||||
GFp_bn_correct_top(res);
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
GFp_BN_free(&tmp);
|
||||
GFp_BN_free(&snum);
|
||||
GFp_BN_free(&sdiv);
|
||||
GFp_BN_free(&res_tmp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int GFp_BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d) {
|
||||
if (!(GFp_BN_mod(r, m, d))) {
|
||||
return 0;
|
||||
}
|
||||
if (!r->neg) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* now -|d| < r < 0, so we have to set r := r + |d|. */
|
||||
return (d->neg ? GFp_BN_sub : GFp_BN_add)(r, r, d);
|
||||
}
|
||||
|
||||
int GFp_BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BIGNUM *m) {
|
||||
|
290
crypto/bn/gcd.c
290
crypto/bn/gcd.c
@ -1,290 +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 <GFp/err.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
int GFp_BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
|
||||
const BIGNUM *n) {
|
||||
*out_no_inverse = 0;
|
||||
|
||||
if (!GFp_BN_is_odd(n)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GFp_BN_is_negative(a) || GFp_BN_cmp(a, n) >= 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_INPUT_NOT_REDUCED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BIGNUM A;
|
||||
GFp_BN_init(&A);
|
||||
|
||||
BIGNUM B;
|
||||
GFp_BN_init(&B);
|
||||
|
||||
BIGNUM X;
|
||||
GFp_BN_init(&X);
|
||||
|
||||
BIGNUM Y;
|
||||
GFp_BN_init(&Y);
|
||||
|
||||
int ret = 0;
|
||||
int sign;
|
||||
|
||||
BIGNUM *R = out;
|
||||
|
||||
GFp_BN_zero(&Y);
|
||||
if (!GFp_BN_set_word(&X, 1) ||
|
||||
!GFp_BN_copy(&B, a) ||
|
||||
!GFp_BN_copy(&A, n)) {
|
||||
goto err;
|
||||
}
|
||||
A.neg = 0;
|
||||
sign = -1;
|
||||
/* From B = a mod |n|, A = |n| it follows that
|
||||
*
|
||||
* 0 <= B < A,
|
||||
* -sign*X*a == B (mod |n|),
|
||||
* sign*Y*a == A (mod |n|).
|
||||
*/
|
||||
|
||||
/* Binary inversion algorithm; requires odd modulus. This is faster than the
|
||||
* general algorithm if the modulus is sufficiently small (about 400 .. 500
|
||||
* bits on 32-bit systems, but much more on 64-bit systems) */
|
||||
int shift;
|
||||
|
||||
while (!GFp_BN_is_zero(&B)) {
|
||||
/* 0 < B < |n|,
|
||||
* 0 < A <= |n|,
|
||||
* (1) -sign*X*a == B (mod |n|),
|
||||
* (2) sign*Y*a == A (mod |n|) */
|
||||
|
||||
/* Now divide B by the maximum possible power of two in the integers,
|
||||
* and divide X by the same value mod |n|.
|
||||
* When we're done, (1) still holds. */
|
||||
shift = 0;
|
||||
while (!GFp_BN_is_bit_set(&B, shift)) {
|
||||
/* note that 0 < B */
|
||||
shift++;
|
||||
|
||||
if (GFp_BN_is_odd(&X)) {
|
||||
if (!GFp_BN_uadd(&X, &X, n)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* now X is even, so we can easily divide it by two */
|
||||
if (!GFp_BN_rshift1(&X, &X)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (shift > 0) {
|
||||
if (!GFp_BN_rshift(&B, &B, shift)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Same for A and Y. Afterwards, (2) still holds. */
|
||||
shift = 0;
|
||||
while (!GFp_BN_is_bit_set(&A, shift)) {
|
||||
/* note that 0 < A */
|
||||
shift++;
|
||||
|
||||
if (GFp_BN_is_odd(&Y)) {
|
||||
if (!GFp_BN_uadd(&Y, &Y, n)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* now Y is even */
|
||||
if (!GFp_BN_rshift1(&Y, &Y)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (shift > 0) {
|
||||
if (!GFp_BN_rshift(&A, &A, shift)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* We still have (1) and (2).
|
||||
* Both A and B are odd.
|
||||
* The following computations ensure that
|
||||
*
|
||||
* 0 <= B < |n|,
|
||||
* 0 < A < |n|,
|
||||
* (1) -sign*X*a == B (mod |n|),
|
||||
* (2) sign*Y*a == A (mod |n|),
|
||||
*
|
||||
* and that either A or B is even in the next iteration. */
|
||||
if (GFp_BN_ucmp(&B, &A) >= 0) {
|
||||
/* -sign*(X + Y)*a == B - A (mod |n|) */
|
||||
if (!GFp_BN_uadd(&X, &X, &Y)) {
|
||||
goto err;
|
||||
}
|
||||
/* NB: we could use GFp_BN_mod_add_quick(X, X, Y, n), but that
|
||||
* actually makes the algorithm slower */
|
||||
if (!GFp_BN_usub(&B, &B, &A)) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
/* sign*(X + Y)*a == A - B (mod |n|) */
|
||||
if (!GFp_BN_uadd(&Y, &Y, &X)) {
|
||||
goto err;
|
||||
}
|
||||
/* as above, GFp_BN_mod_add_quick(Y, Y, X, n) would slow things down */
|
||||
if (!GFp_BN_usub(&A, &A, &B)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!GFp_BN_is_one(&A)) {
|
||||
*out_no_inverse = 1;
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* The while loop (Euclid's algorithm) ends when
|
||||
* A == gcd(a,n);
|
||||
* we have
|
||||
* sign*Y*a == A (mod |n|),
|
||||
* where Y is non-negative. */
|
||||
|
||||
if (sign < 0) {
|
||||
if (!GFp_BN_sub(&Y, n, &Y)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* Now Y*a == A (mod |n|). */
|
||||
|
||||
/* Y*a == 1 (mod |n|) */
|
||||
if (!Y.neg && GFp_BN_ucmp(&Y, n) < 0) {
|
||||
if (!GFp_BN_copy(R, &Y)) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!GFp_BN_nnmod(R, &Y, n)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
GFp_BN_free(&A);
|
||||
GFp_BN_free(&B);
|
||||
GFp_BN_free(&X);
|
||||
GFp_BN_free(&Y);
|
||||
|
||||
return ret;
|
||||
}
|
@ -56,146 +56,9 @@
|
||||
|
||||
#include <GFp/bn.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <GFp/err.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
int GFp_BN_lshift(BIGNUM *r, const BIGNUM *a, int n) {
|
||||
int i, nw, lb, rb;
|
||||
BN_ULONG *t, *f;
|
||||
BN_ULONG l;
|
||||
|
||||
if (n < 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->neg = a->neg;
|
||||
nw = n / BN_BITS2;
|
||||
if (!GFp_bn_wexpand(r, a->top + nw + 1)) {
|
||||
return 0;
|
||||
}
|
||||
lb = n % BN_BITS2;
|
||||
rb = BN_BITS2 - lb;
|
||||
f = a->d;
|
||||
t = r->d;
|
||||
t[a->top + nw] = 0;
|
||||
if (lb == 0) {
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
t[nw + i] = f[i];
|
||||
}
|
||||
} else {
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
l = f[i];
|
||||
t[nw + i + 1] |= (l >> rb) & BN_MASK2;
|
||||
t[nw + i] = (l << lb) & BN_MASK2;
|
||||
}
|
||||
}
|
||||
memset(t, 0, nw * sizeof(t[0]));
|
||||
r->top = a->top + nw + 1;
|
||||
GFp_bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GFp_BN_rshift(BIGNUM *r, const BIGNUM *a, int n) {
|
||||
int i, j, nw, lb, rb;
|
||||
BN_ULONG *t, *f;
|
||||
BN_ULONG l, tmp;
|
||||
|
||||
if (n < 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nw = n / BN_BITS2;
|
||||
rb = n % BN_BITS2;
|
||||
lb = BN_BITS2 - rb;
|
||||
if (nw >= a->top || a->top == 0) {
|
||||
GFp_BN_zero(r);
|
||||
return 1;
|
||||
}
|
||||
i = (GFp_BN_num_bits(a) - n + (BN_BITS2 - 1)) / BN_BITS2;
|
||||
if (r != a) {
|
||||
r->neg = a->neg;
|
||||
if (!GFp_bn_wexpand(r, i)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (n == 0) {
|
||||
return 1; /* or the copying loop will go berserk */
|
||||
}
|
||||
}
|
||||
|
||||
f = &(a->d[nw]);
|
||||
t = r->d;
|
||||
j = a->top - nw;
|
||||
r->top = i;
|
||||
|
||||
if (rb == 0) {
|
||||
for (i = j; i != 0; i--) {
|
||||
*(t++) = *(f++);
|
||||
}
|
||||
} else {
|
||||
l = *(f++);
|
||||
for (i = j - 1; i != 0; i--) {
|
||||
tmp = (l >> rb) & BN_MASK2;
|
||||
l = *(f++);
|
||||
*(t++) = (tmp | (l << lb)) & BN_MASK2;
|
||||
}
|
||||
l = (l >> rb) & BN_MASK2;
|
||||
if (l != 0) {
|
||||
*(t) = l;
|
||||
}
|
||||
}
|
||||
|
||||
if (r->top == 0) {
|
||||
r->neg = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GFp_BN_rshift1(BIGNUM *r, const BIGNUM *a) {
|
||||
BN_ULONG *ap, *rp, t, c;
|
||||
int i, j;
|
||||
|
||||
if (GFp_BN_is_zero(a)) {
|
||||
GFp_BN_zero(r);
|
||||
return 1;
|
||||
}
|
||||
i = a->top;
|
||||
ap = a->d;
|
||||
j = i - (ap[i - 1] == 1);
|
||||
if (a != r) {
|
||||
if (!GFp_bn_wexpand(r, j)) {
|
||||
return 0;
|
||||
}
|
||||
r->neg = a->neg;
|
||||
}
|
||||
rp = r->d;
|
||||
t = ap[--i];
|
||||
c = (t & 1) ? BN_TBIT : 0;
|
||||
if (t >>= 1) {
|
||||
rp[i] = t;
|
||||
}
|
||||
while (i > 0) {
|
||||
t = ap[--i];
|
||||
rp[i] = ((t >> 1) & BN_MASK2) | c;
|
||||
c = (t & 1) ? BN_TBIT : 0;
|
||||
}
|
||||
r->top = j;
|
||||
|
||||
if (r->top == 0) {
|
||||
r->neg = 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int GFp_BN_set_bit(BIGNUM *a, int n) {
|
||||
int i, j, k;
|
||||
|
||||
|
1
crypto/test/.gitattributes
vendored
1
crypto/test/.gitattributes
vendored
@ -1 +0,0 @@
|
||||
*.h linguist-language=C++
|
@ -1,181 +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 "bn_test_util.h"
|
||||
#include "bn_test_lib.h"
|
||||
|
||||
#include <GFp/bn.h>
|
||||
#include <GFp/err.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "../bn/internal.h"
|
||||
|
||||
|
||||
static int bn_expand(BIGNUM *bn, size_t bits) {
|
||||
if (bits + BN_BITS2 - 1 < bits) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
return GFp_bn_wexpand(bn, (bits+BN_BITS2-1)/BN_BITS2);
|
||||
}
|
||||
|
||||
/* decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|. */
|
||||
static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
|
||||
if (in_len > INT_MAX/4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
/* |in_len| is the number of hex digits. */
|
||||
if (!bn_expand(bn, in_len * 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (in_len > 0) {
|
||||
/* Decode one |BN_ULONG| at a time. */
|
||||
int todo = BN_BYTES * 2;
|
||||
if (todo > in_len) {
|
||||
todo = in_len;
|
||||
}
|
||||
|
||||
BN_ULONG word = 0;
|
||||
int j;
|
||||
for (j = todo; j > 0; j--) {
|
||||
char c = in[in_len - j];
|
||||
|
||||
BN_ULONG hex;
|
||||
if (c >= '0' && c <= '9') {
|
||||
hex = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
hex = c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
hex = c - 'A' + 10;
|
||||
} else {
|
||||
hex = 0;
|
||||
/* This shouldn't happen. The caller checks |isxdigit|. */
|
||||
assert(0);
|
||||
}
|
||||
word = (word << 4) | hex;
|
||||
}
|
||||
|
||||
bn->d[i++] = word;
|
||||
in_len -= todo;
|
||||
}
|
||||
assert(i <= bn->dmax);
|
||||
bn->top = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len);
|
||||
typedef int (*char_test_func) (int c);
|
||||
|
||||
static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
|
||||
BIGNUM *ret = NULL;
|
||||
int neg = 0, i;
|
||||
int num;
|
||||
|
||||
if (in == NULL || *in == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*in == '-') {
|
||||
neg = 1;
|
||||
in++;
|
||||
}
|
||||
|
||||
for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {}
|
||||
|
||||
num = i + neg;
|
||||
if (outp == NULL) {
|
||||
return num;
|
||||
}
|
||||
|
||||
/* in is the start of the hex digits, and it is 'i' long */
|
||||
if (*outp == NULL) {
|
||||
ret = GFp_BN_new();
|
||||
if (ret == NULL) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = *outp;
|
||||
GFp_BN_zero(ret);
|
||||
}
|
||||
|
||||
if (!decode(ret, in, i)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
GFp_bn_correct_top(ret);
|
||||
if (!GFp_BN_is_zero(ret)) {
|
||||
ret->neg = neg;
|
||||
}
|
||||
|
||||
*outp = ret;
|
||||
return num;
|
||||
|
||||
err:
|
||||
if (*outp == NULL) {
|
||||
GFp_BN_free(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GFp_BN_hex2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_hex, isxdigit);
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
/* Copyright (C) 1995-1997 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-2006 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).
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the Eric Young open source
|
||||
* license provided above.
|
||||
*
|
||||
* The binary polynomial arithmetic software is originally written by
|
||||
* Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
|
||||
* Laboratories. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_BN_TEST_LIB_H
|
||||
#define OPENSSL_HEADER_BN_TEST_LIB_H
|
||||
|
||||
#include <GFp/base.h>
|
||||
#include <GFp/bn.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* BIGNUM functions that used to be in libcrypto, but which were removed
|
||||
* because no library code uses them anymore. They are retained here so that
|
||||
* bn_test.cc can use them to test functions that still remain in libcrypto. */
|
||||
|
||||
/* Basic functions. */
|
||||
|
||||
/* GFp_BN_new creates a new, allocated BIGNUM and initialises it. */
|
||||
BIGNUM *GFp_BN_new(void);
|
||||
|
||||
/* GFp_BN_num_bytes returns the minimum number of bytes needed to represent the
|
||||
* absolute value of |bn|. */
|
||||
OPENSSL_EXPORT unsigned GFp_BN_num_bytes(const BIGNUM *bn);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_BN_TEST_LIB_H */
|
@ -1,82 +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 <string.h>
|
||||
|
||||
#include <GFp/err.h>
|
||||
#include <GFp/mem.h>
|
||||
|
||||
#include "../test/bn_test_lib.h"
|
||||
|
||||
BIGNUM *GFp_BN_new(void) {
|
||||
BIGNUM *bn = OPENSSL_malloc(sizeof(BIGNUM));
|
||||
|
||||
if (bn == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(bn, 0, sizeof(BIGNUM));
|
||||
bn->flags = BN_FLG_MALLOCED;
|
||||
|
||||
return bn;
|
||||
}
|
||||
|
||||
unsigned GFp_BN_num_bytes(const BIGNUM *bn) {
|
||||
return (GFp_BN_num_bits(bn) + 7) / 8;
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
/* Copyright (C) 1995-1997 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-2006 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).
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the Eric Young open source
|
||||
* license provided above.
|
||||
*
|
||||
* The binary polynomial arithmetic software is originally written by
|
||||
* Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
|
||||
* Laboratories. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_CRYPTO_TEST_BN_TEST_UTIL_H
|
||||
#define OPENSSL_HEADER_CRYPTO_TEST_BN_TEST_UTIL_H
|
||||
|
||||
#include <GFp/bn.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* BN_hex2bn parses the leading hex number from |in|, which may be proceeded by
|
||||
* a '-' to indicate a negative number and may contain trailing, non-hex data.
|
||||
* If |outp| is not NULL, it constructs a BIGNUM equal to the hex number and
|
||||
* stores it in |*outp|. If |*outp| is NULL then it allocates a new BIGNUM and
|
||||
* updates |*outp|. It returns the number of bytes of |in| processed or zero on
|
||||
* error. */
|
||||
OPENSSL_EXPORT int GFp_BN_hex2bn(BIGNUM **outp, const char *in);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_CRYPTO_TEST_BN_TEST_UTIL_H */
|
@ -1,199 +0,0 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable: 4996) // This function or variable may be unsafe.
|
||||
#endif
|
||||
|
||||
#include "file_test.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <GFp/err.h>
|
||||
|
||||
|
||||
FileTest::FileTest(const char *path)
|
||||
: file_(nullptr),
|
||||
line_(0),
|
||||
start_line_(0)
|
||||
{
|
||||
file_ = fopen(path, "r");
|
||||
if (file_ == nullptr) {
|
||||
fprintf(stderr, "Could not open file %s: %s.\n", path, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
FileTest::~FileTest() {
|
||||
if (file_ != nullptr) {
|
||||
fclose(file_);
|
||||
}
|
||||
}
|
||||
|
||||
// FindDelimiter returns a pointer to the first '=' or ':' in |str| or nullptr
|
||||
// if there is none.
|
||||
static const char *FindDelimiter(const char *str) {
|
||||
while (*str) {
|
||||
if (*str == ':' || *str == '=') {
|
||||
return str;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// StripSpace returns a string containing up to |len| characters from |str| with
|
||||
// leading and trailing whitespace removed.
|
||||
static std::string StripSpace(const char *str, size_t len) {
|
||||
// Remove leading space.
|
||||
while (len > 0 && isspace(*str)) {
|
||||
str++;
|
||||
len--;
|
||||
}
|
||||
while (len > 0 && isspace(str[len-1])) {
|
||||
len--;
|
||||
}
|
||||
return std::string(str, len);
|
||||
}
|
||||
|
||||
FileTest::ReadResult FileTest::ReadNext() {
|
||||
// If the previous test had unused attributes, it is an error.
|
||||
if (!unused_attributes_.empty()) {
|
||||
for (const std::string &key : unused_attributes_) {
|
||||
PrintLine("Unused attribute: ", key.c_str());
|
||||
}
|
||||
return kReadError;
|
||||
}
|
||||
|
||||
ClearTest();
|
||||
|
||||
static const size_t kBufLen = 64 + 8192*2;
|
||||
std::unique_ptr<char[]> buf(new char[kBufLen]);
|
||||
|
||||
while (true) {
|
||||
// Read the next line.
|
||||
if (fgets(buf.get(), kBufLen, file_) == nullptr) {
|
||||
if (feof(file_)) {
|
||||
// EOF is a valid terminator for a test.
|
||||
return start_line_ > 0 ? kReadSuccess : kReadEOF;
|
||||
}
|
||||
fprintf(stderr, "Error reading from input.\n");
|
||||
return kReadError;
|
||||
}
|
||||
|
||||
line_++;
|
||||
size_t len = strlen(buf.get());
|
||||
// Check for truncation.
|
||||
if (len > 0 && buf[len - 1] != '\n' && !feof(file_)) {
|
||||
fprintf(stderr, "Line %u too long.\n", line_);
|
||||
return kReadError;
|
||||
}
|
||||
|
||||
if (buf[0] == '\n' || buf[0] == '\0') {
|
||||
// Empty lines delimit tests.
|
||||
if (start_line_ > 0) {
|
||||
return kReadSuccess;
|
||||
}
|
||||
} else if (buf[0] != '#') { // Comment lines are ignored.
|
||||
// Parse the line as an attribute.
|
||||
const char *delimiter = FindDelimiter(buf.get());
|
||||
if (delimiter == nullptr) {
|
||||
fprintf(stderr, "Line %u: Could not parse attribute.\n", line_);
|
||||
return kReadError;
|
||||
}
|
||||
std::string key = StripSpace(buf.get(),
|
||||
static_cast<size_t>(delimiter - buf.get()));
|
||||
std::string value = StripSpace(
|
||||
delimiter + 1, static_cast<size_t>(buf.get() + len - delimiter - 1));
|
||||
|
||||
unused_attributes_.insert(key);
|
||||
attributes_[key] = value;
|
||||
if (start_line_ == 0) {
|
||||
// This is the start of a test.
|
||||
type_ = key;
|
||||
parameter_ = value;
|
||||
start_line_ = line_;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileTest::PrintLine(const char *p1, const char *p2, const char *p3) {
|
||||
fprintf(stderr, "Line %u: %s%s%s\n", start_line_, p1, p2, p3);
|
||||
}
|
||||
|
||||
const std::string &FileTest::GetType() {
|
||||
OnKeyUsed(type_);
|
||||
return type_;
|
||||
}
|
||||
|
||||
bool FileTest::GetAttribute(std::string *out_value, const std::string &key) {
|
||||
OnKeyUsed(key);
|
||||
auto iter = attributes_.find(key);
|
||||
if (iter == attributes_.end()) {
|
||||
PrintLine("Missing attribute '", key.c_str(), "'.");
|
||||
return false;
|
||||
}
|
||||
*out_value = iter->second;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FileTest::ClearTest() {
|
||||
start_line_ = 0;
|
||||
type_.clear();
|
||||
parameter_.clear();
|
||||
attributes_.clear();
|
||||
unused_attributes_.clear();
|
||||
}
|
||||
|
||||
void FileTest::OnKeyUsed(const std::string &key) {
|
||||
unused_attributes_.erase(key);
|
||||
}
|
||||
|
||||
int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg,
|
||||
const char *path) {
|
||||
FileTest t(path);
|
||||
if (!t.is_open()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool failed = false;
|
||||
while (true) {
|
||||
FileTest::ReadResult ret = t.ReadNext();
|
||||
if (ret == FileTest::kReadError) {
|
||||
return 1;
|
||||
} else if (ret == FileTest::kReadEOF) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool result = run_test(&t, arg);
|
||||
if (!result) {
|
||||
// In case the test itself doesn't print output, print something so the
|
||||
// line number is reported.
|
||||
t.PrintLine("Test failed");
|
||||
failed = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
|
||||
#define OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
// File-based test framework.
|
||||
//
|
||||
// This module provides a file-based test framework. The file format is based on
|
||||
// that of OpenSSL upstream's evp_test and BoringSSL's aead_test. Each input
|
||||
// file is a sequence of attributes and blank lines.
|
||||
//
|
||||
// Each attribute has the form:
|
||||
//
|
||||
// Name = Value
|
||||
//
|
||||
// Either '=' or ':' may be used to delimit the name from the value. Both the
|
||||
// name and value have leading and trailing spaces stripped.
|
||||
//
|
||||
// Lines beginning with # are ignored.
|
||||
//
|
||||
// A test is a sequence of one or more attributes followed by a blank line.
|
||||
// Blank lines are otherwise ignored. For tests that process multiple kinds of
|
||||
// test cases, the first attribute is parsed out as the test's type and
|
||||
// parameter. Otherwise, attributes are unordered. The first attribute is also
|
||||
// included in the set of attributes, so tests which do not dispatch may ignore
|
||||
// this mechanism.
|
||||
//
|
||||
// Functions in this module freely output to |stderr| on failure. Tests should
|
||||
// also do so, and it is recommended they include the corresponding test's line
|
||||
// number in any output. |PrintLine| does this automatically.
|
||||
//
|
||||
// Each attribute in a test must be consumed. When a test completes, if any
|
||||
// attributes haven't been processed, the framework reports an error.
|
||||
|
||||
|
||||
class FileTest {
|
||||
public:
|
||||
explicit FileTest(const char *path);
|
||||
~FileTest();
|
||||
|
||||
// is_open returns true if the file was successfully opened.
|
||||
bool is_open() const { return file_ != nullptr; }
|
||||
|
||||
enum ReadResult {
|
||||
kReadSuccess,
|
||||
kReadEOF,
|
||||
kReadError
|
||||
};
|
||||
|
||||
// ReadNext reads the next test from the file. It returns |kReadSuccess| if
|
||||
// successfully reading a test and |kReadEOF| at the end of the file. On
|
||||
// error or if the previous test had unconsumed attributes, it returns
|
||||
// |kReadError|.
|
||||
ReadResult ReadNext();
|
||||
|
||||
// PrintLine is a simple printer that prints strings the concatenation of
|
||||
// |*p1|, |*p2|, and |*p3|, prepending the line number and appending a
|
||||
// trailing newline.
|
||||
void PrintLine(const char *p1, const char *p2 = "", const char *p3 = "");
|
||||
|
||||
unsigned start_line() const { return start_line_; }
|
||||
|
||||
// GetType returns the name of the first attribute of the current test.
|
||||
const std::string &GetType();
|
||||
|
||||
// GetAttribute looks up the attribute with key |key|. It sets |*out_value| to
|
||||
// the value and returns true if it exists and returns false with an error to
|
||||
// |stderr| otherwise.
|
||||
bool GetAttribute(std::string *out_value, const std::string &key);
|
||||
|
||||
private:
|
||||
void ClearTest();
|
||||
void OnKeyUsed(const std::string &key);
|
||||
|
||||
FILE *file_;
|
||||
// line_ is the number of lines read.
|
||||
unsigned line_;
|
||||
|
||||
// start_line_ is the line number of the first attribute of the test.
|
||||
unsigned start_line_;
|
||||
// type_ is the name of the first attribute of the test.
|
||||
std::string type_;
|
||||
// parameter_ is the value of the first attribute.
|
||||
std::string parameter_;
|
||||
// attributes_ contains all attributes in the test, including the first.
|
||||
std::map<std::string, std::string> attributes_;
|
||||
|
||||
// unused_attributes_ is the set of attributes that have been queried.
|
||||
std::set<std::string> unused_attributes_;
|
||||
|
||||
FileTest(const FileTest&) = delete;
|
||||
FileTest &operator=(const FileTest&) = delete;
|
||||
};
|
||||
|
||||
// FileTestMain runs a file-based test out of |path| and returns an exit code
|
||||
// suitable to return out of |main|. |run_test| should return true on pass and
|
||||
// false on failure. FileTestMain also implements common handling of the 'Error'
|
||||
// attribute. A test with that attribute is expected to fail. The value of the
|
||||
// attribute is the reason string of the expected OpenSSL error code.
|
||||
//
|
||||
// Tests are guaranteed to run serially and may affect global state if need be.
|
||||
// It is legal to use "tests" which, for example, import a private key into a
|
||||
// list of keys. This may be used to initialize a shared set of keys for many
|
||||
// tests. However, if one test fails, the framework will continue to run
|
||||
// subsequent tests.
|
||||
int FileTestMain(bool (*run_test)(FileTest *t, void *arg), void *arg,
|
||||
const char *path);
|
||||
|
||||
|
||||
#endif /* OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H */
|
@ -1,49 +0,0 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
|
||||
#define OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
|
||||
|
||||
// Avoid "C4548: expression before comma has no effect; expected expression
|
||||
// with side-effect." in malloc.h in Visual Studio 2015 Update 1 in debug mode.
|
||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4548)
|
||||
#endif
|
||||
|
||||
#include <memory>
|
||||
|
||||
#if defined(_MSC_VER) && defined(_DEBUG)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include <GFp/bn.h>
|
||||
|
||||
template<typename T, void (*func)(T*)>
|
||||
struct OpenSSLDeleter {
|
||||
void operator()(T *obj) {
|
||||
func(obj);
|
||||
}
|
||||
};
|
||||
|
||||
// XXX: GCC 4.6 doesn't support this use of `using` yet:
|
||||
// template<typename T, void (*func)(T*)>
|
||||
// using ScopedOpenSSLType = std::unique_ptr<T, OpenSSLDeleter<T, func>>;
|
||||
// TODO: When we drop GCC 4.6 support, revert back to what BoringSSL is doing.
|
||||
#define SCOPED_OPENSSL_TYPE(Name, T, func) \
|
||||
typedef std::unique_ptr<T, OpenSSLDeleter<T, func>> Name
|
||||
|
||||
SCOPED_OPENSSL_TYPE(ScopedBIGNUM, BIGNUM, GFp_BN_free);
|
||||
|
||||
#endif // OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
|
@ -237,14 +237,6 @@ OPENSSL_EXPORT int GFp_BN_usub_unchecked(BIGNUM *r, const BIGNUM *a,
|
||||
* 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);
|
||||
|
||||
/* GFp_BN_div divides |numerator| by |divisor| and places the result in
|
||||
* |quotient| and the remainder in |rem|. Either of |quotient| or |rem| may be
|
||||
* NULL, in which case the respective value is not returned. The result is
|
||||
* rounded towards zero; thus if |numerator| is negative, the remainder will be
|
||||
* zero or negative. It returns one on success or zero on error. */
|
||||
OPENSSL_EXPORT int GFp_BN_div(BIGNUM *quotient, BIGNUM *rem,
|
||||
const BIGNUM *numerator, const BIGNUM *divisor);
|
||||
|
||||
|
||||
/* Comparison functions */
|
||||
|
||||
@ -277,19 +269,6 @@ OPENSSL_EXPORT int GFp_BN_is_odd(const BIGNUM *bn);
|
||||
|
||||
/* Bitwise operations. */
|
||||
|
||||
/* GFp_BN_lshift sets |r| equal to |a| << n. The |a| and |r| arguments may be
|
||||
* the same |BIGNUM|. It returns one on success and zero on allocation failure.
|
||||
*/
|
||||
OPENSSL_EXPORT int GFp_BN_lshift(BIGNUM *r, const BIGNUM *a, int n);
|
||||
|
||||
/* GFp_BN_rshift sets |r| equal to |a| >> n, where |r| and |a| may be the same
|
||||
* pointer. It returns one on success and zero on allocation failure. */
|
||||
OPENSSL_EXPORT int GFp_BN_rshift(BIGNUM *r, const BIGNUM *a, int n);
|
||||
|
||||
/* GFp_BN_rshift1 sets |r| equal to |a| >> 1, where |r| and |a| may be the same
|
||||
* pointer. It returns one on success and zero on allocation failure. */
|
||||
OPENSSL_EXPORT int GFp_BN_rshift1(BIGNUM *r, const BIGNUM *a);
|
||||
|
||||
/* GFp_BN_set_bit sets the |n|th, least-significant bit in |a|. For example, if
|
||||
* |a| is 2 then setting bit zero will make it 3. It returns one on success or
|
||||
* zero on allocation failure. */
|
||||
@ -302,17 +281,6 @@ OPENSSL_EXPORT int GFp_BN_is_bit_set(const BIGNUM *a, int n);
|
||||
|
||||
/* Modulo arithmetic. */
|
||||
|
||||
/* GFp_BN_mod is a helper macro that calls |GFp_BN_div| and discards the
|
||||
* quotient. */
|
||||
#define GFp_BN_mod(rem, numerator, divisor) \
|
||||
GFp_BN_div(NULL, (rem), (numerator), (divisor))
|
||||
|
||||
/* GFp_BN_nnmod is a non-negative modulo function. It acts like |GFp_BN_mod|,
|
||||
* but 0 <= |rem| < |divisor| is always true. It returns one on success and
|
||||
* zero on error. */
|
||||
OPENSSL_EXPORT int GFp_BN_nnmod(BIGNUM *rem, const BIGNUM *numerator,
|
||||
const BIGNUM *divisor);
|
||||
|
||||
/* GFp_BN_mod_add_quick acts like |BN_mod_add| but requires that |a| and |b| be
|
||||
* non-negative and less than |m|. */
|
||||
OPENSSL_EXPORT int GFp_BN_mod_add_quick(BIGNUM *r, const BIGNUM *a,
|
||||
|
@ -188,10 +188,5 @@ mod private {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[cfg(all(feature = "use_heap",
|
||||
feature = "bn_tests",
|
||||
not(any(target_os = "macos", target_os = "ios", target_env = "musl"))))]
|
||||
bssl_test!(test_bn, bssl_bn_test_main);
|
||||
|
||||
bssl_test!(test_constant_time, bssl_constant_time_test_main);
|
||||
}
|
||||
|
@ -15,8 +15,6 @@
|
||||
|
||||
//! Generation of random field elements, in particular field elements in GFn
|
||||
//! where *n* is an RSA public modulus.
|
||||
//!
|
||||
//! This is also used for some randomized tests in bn_tests.cc.
|
||||
|
||||
use {c, core, rand, error, rsa};
|
||||
use limb::*;
|
||||
|
Loading…
x
Reference in New Issue
Block a user