@@ -7,10 +7,13 @@ MACHINE := $(shell uname -m) | |||
ifeq ($(UNAME),Darwin) | |||
CC = clang | |||
CXX = clang++ | |||
else | |||
CC = gcc | |||
CXX = g++ | |||
endif | |||
LD = $(CC) | |||
LDXX = $(CXX) | |||
ASM ?= $(CC) | |||
DECAF ?= decaf | |||
@@ -30,6 +33,7 @@ WARNFLAGS = -pedantic -Wall -Wextra -Werror -Wunreachable-code \ | |||
INCFLAGS = -Isrc/include -Iinclude -Isrc/$(FIELD) -Isrc/$(FIELD)/$(ARCH) | |||
LANGFLAGS = -std=c99 -fno-strict-aliasing | |||
LANGXXFLAGS = -fno-strict-aliasing | |||
GENFLAGS = -ffunction-sections -fdata-sections -fvisibility=hidden -fomit-frame-pointer -fPIC | |||
OFLAGS = -O3 | |||
@@ -58,6 +62,7 @@ endif | |||
ARCHFLAGS += $(XARCHFLAGS) | |||
CFLAGS = $(LANGFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCFLAGS) | |||
CXXFLAGS = $(LANGXXFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCXXFLAGS) | |||
LDFLAGS = $(ARCHFLAGS) $(XLDFLAGS) | |||
ASFLAGS = $(ARCHFLAGS) $(XASFLAGS) | |||
@@ -81,6 +86,8 @@ TESTCOMPONENTS=build/test.o build/test_scalarmul.o build/test_sha512.o \ | |||
build/test_pointops.o build/test_arithmetic.o build/test_goldilocks.o build/magic.o \ | |||
build/shake.o | |||
TESTDECAFCOMPONENTS=build/test_decaf.o | |||
BENCHCOMPONENTS = build/bench.o build/shake.o | |||
BATBASE=ed448goldilocks-bats-$(TODAY) | |||
@@ -92,42 +99,45 @@ scan: clean | |||
scan-build --use-analyzer=`which clang` \ | |||
-enable-checker deadcode -enable-checker llvm \ | |||
-enable-checker osx -enable-checker security -enable-checker unix \ | |||
make build/bench build/test build/goldilocks.so | |||
make build/bench build/test all | |||
build/bench: $(LIBCOMPONENTS) $(BENCHCOMPONENTS) $(DECAFCOMPONENTS) | |||
$(LD) $(LDFLAGS) -o $@ $^ | |||
build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) $(DECAFCOMPONENTS) | |||
$(LD) $(LDFLAGS) -o $@ $^ -lgmp | |||
build/test_decaf: $(TESTDECAFCOMPONENTS) decaf_lib | |||
$(LDXX) $(LDFLAGS) -o $@ $< -lgmp -Lbuild -ldecaf | |||
build/shakesum: build/shakesum.o build/shake.o | |||
$(LD) $(LDFLAGS) -o $@ $^ | |||
lib: build/goldilocks.so | |||
lib: build/libgoldilocks.so | |||
decaf_lib: build/decaf.so | |||
decaf_lib: build/libdecaf.so | |||
build/goldilocks.so: $(LIBCOMPONENTS) | |||
build/libgoldilocks.so: $(LIBCOMPONENTS) | |||
rm -f $@ | |||
ifeq ($(UNAME),Darwin) | |||
libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ | |||
$(LIBCOMPONENTS) | |||
else | |||
$(LD) $(LDFLAGS) -shared -Wl,-soname,goldilocks.so.1 -Wl,--gc-sections -o $@ $(LIBCOMPONENTS) | |||
$(LD) $(LDFLAGS) -shared -Wl,-soname,libgoldilocks.so.1 -Wl,--gc-sections -o $@ $(LIBCOMPONENTS) | |||
strip --discard-all $@ | |||
ln -sf `basename $@` build/goldilocks.so.1 | |||
ln -sf `basename $@` build/libgoldilocks.so.1 | |||
endif | |||
build/decaf.so: $(DECAFCOMPONENTS) | |||
build/libdecaf.so: $(DECAFCOMPONENTS) | |||
rm -f $@ | |||
ifeq ($(UNAME),Darwin) | |||
libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ | |||
$(DECAFCOMPONENTS) | |||
else | |||
$(LD) $(LDFLAGS) -shared -Wl,-soname,goldilocks.so.1 -Wl,--gc-sections -o $@ $(DECAFCOMPONENTS) | |||
$(LD) $(LDFLAGS) -shared -Wl,-soname,libdecaf.so.1 -Wl,--gc-sections -o $@ $(DECAFCOMPONENTS) | |||
strip --discard-all $@ | |||
ln -sf `basename $@` build/goldilocks.so.1 | |||
ln -sf `basename $@` build/libdecaf.so.1 | |||
endif | |||
build/timestamp: | |||
@@ -148,10 +158,16 @@ build/decaf_tables.s: build/decaf_tables.c $(HEADERS) | |||
build/%.s: src/%.c $(HEADERS) | |||
$(CC) $(CFLAGS) -S -c -o $@ $< | |||
build/%.s: src/%.cxx $(HEADERS) | |||
$(CXX) $(CXXFLAGS) -S -c -o $@ $< | |||
build/%.s: test/%.c $(HEADERS) | |||
$(CC) $(CFLAGS) -S -c -o $@ $< | |||
build/%.s: test/%.cxx $(HEADERS) | |||
$(CXX) $(CXXFLAGS) -S -c -o $@ $< | |||
build/%.s: src/$(FIELD)/$(ARCH)/%.c $(HEADERS) | |||
$(CC) $(CFLAGS) -S -c -o $@ $< | |||
@@ -203,8 +219,11 @@ todo:: | |||
bench: build/bench | |||
./$< | |||
test: build/test | |||
./$< | |||
test: build/test test_decaf | |||
build/test | |||
test_decaf: build/test_decaf | |||
LD_LIBRARY_PATH=`pwd`/build:$(LD_LIBRARY_PATH) build/test_decaf | |||
clean: | |||
rm -fr build doc $(BATNAME) |
@@ -76,7 +76,7 @@ struct decaf_448_precomputed_s; | |||
typedef struct decaf_448_precomputed_s decaf_448_precomputed_s; | |||
/** Size and alignment of precomputed point tables. */ | |||
extern const size_t sizeof_decaf_448_precomputed_s, alignof_decaf_448_precomputed_s; | |||
extern const size_t sizeof_decaf_448_precomputed_s API_VIS, alignof_decaf_448_precomputed_s API_VIS; | |||
/** Scalar is stored packed, because we don't need the speed. */ | |||
typedef struct decaf_448_scalar_s { | |||
@@ -520,7 +520,6 @@ void decaf_448_point_from_hash_uniform ( | |||
/** | |||
* @brief Overwrite data with zeros. Uses memset_s if available. | |||
* If data is NULL, this function has no effect. | |||
*/ | |||
void decaf_bzero ( | |||
void *data, | |||
@@ -562,7 +561,7 @@ void decaf_448_precomputed_destroy ( | |||
#undef NONNULL5 | |||
#ifdef __cplusplus | |||
}; /* extern "C" */ | |||
} /* extern "C" */ | |||
#endif | |||
#endif /* __DECAF_448_H__ */ |
@@ -28,6 +28,8 @@ | |||
#include "decaf.h" | |||
#include <string> | |||
#include <sys/types.h> | |||
#include <limits.h> | |||
/* TODO: document */ | |||
/* TODO: This is incomplete */ | |||
@@ -38,7 +40,7 @@ | |||
#define EXPLICIT_CON explicit | |||
#define GET_DATA(str) ((const unsigned char *)&(str)[0]) | |||
#else | |||
#define NOEXCEPT | |||
#define NOEXCEPT throw() | |||
#define EXPLICIT_CON | |||
#define GET_DATA(str) ((const unsigned char *)((str).data())) | |||
#endif | |||
@@ -50,18 +52,36 @@ void really_bzero(void *data, size_t size); | |||
template<unsigned int bits = 448> struct decaf; | |||
template<> struct decaf<448> { | |||
class CryptoException : public std::exception { | |||
public: | |||
CryptoException() {} | |||
virtual ~CryptoException() NOEXCEPT {} | |||
virtual const char * what() const NOEXCEPT { return "CryptoException"; } | |||
}; | |||
class Point; | |||
class Precomputed; | |||
class Scalar { | |||
public: | |||
decaf_448_scalar_t s; | |||
inline Scalar() NOEXCEPT {} | |||
inline Scalar(const decaf_word_t w) NOEXCEPT { decaf_448_scalar_set(s,w); } | |||
inline Scalar(const int w) NOEXCEPT { | |||
Scalar t(-(decaf_word_t)INT_MIN); | |||
decaf_448_scalar_set(s,(decaf_word_t)w - (decaf_word_t)INT_MIN); | |||
*this -= t; | |||
} | |||
inline Scalar(const decaf_448_scalar_t &t) NOEXCEPT { decaf_448_scalar_copy(s,t); } | |||
inline Scalar(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); } | |||
inline Scalar& operator=(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); return *this; } | |||
inline ~Scalar() NOEXCEPT { decaf_448_scalar_destroy(s); } | |||
/* Initialize from buffer */ | |||
inline explicit Scalar(const std::string &str) NOEXCEPT { decaf_448_scalar_decode_long(s,GET_DATA(str),str.length()); } | |||
inline Scalar &operator=(const std::string &str) NOEXCEPT { | |||
decaf_448_scalar_decode_long(s,GET_DATA(str),str.length()); return *this; | |||
} | |||
inline explicit Scalar(const std::string &str) NOEXCEPT { *this = str; } | |||
inline Scalar(const unsigned char *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,buffer,n); } | |||
inline Scalar(const char *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,(const unsigned char *)buffer,n); } | |||
inline Scalar(const void *buffer, size_t n) NOEXCEPT { decaf_448_scalar_decode_long(s,(const unsigned char *)buffer,n); } | |||
@@ -81,7 +101,7 @@ public: | |||
decaf_448_scalar_encode(buffer, s); | |||
return std::string((char*)buffer,sizeof(buffer)); | |||
} | |||
inline void write_to_buffer(unsigned char buffer[DECAF_448_SCALAR_BYTES]) const NOEXCEPT{ | |||
inline void encode(unsigned char buffer[DECAF_448_SCALAR_BYTES]) const NOEXCEPT{ | |||
decaf_448_scalar_encode(buffer, s); | |||
} | |||
@@ -92,8 +112,15 @@ public: | |||
inline Scalar operator-=(const Scalar &q) NOEXCEPT { decaf_448_scalar_sub(s,s,q.s); return *this; } | |||
inline Scalar operator* (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_mul(r.s,s,q.s); return r; } | |||
inline Scalar operator*=(const Scalar &q) NOEXCEPT { decaf_448_scalar_mul(s,s,q.s); return *this; } | |||
inline Scalar inverse() const NOEXCEPT { Scalar r; decaf_448_scalar_invert(r.s,s); return r; } | |||
inline Scalar operator/ (const Scalar &q) const NOEXCEPT { Scalar r; decaf_448_scalar_mul(r.s,s,q.inverse().s); return r; } | |||
inline Scalar operator/=(const Scalar &q) NOEXCEPT { decaf_448_scalar_mul(s,s,q.inverse().s); return *this; } | |||
inline Scalar operator- () const NOEXCEPT { Scalar r; decaf_448_scalar_sub(r.s,decaf_448_scalar_zero,s); return r; } | |||
inline bool operator!=(const Scalar &q) const NOEXCEPT { return ! decaf_448_scalar_eq(s,q.s); } | |||
inline bool operator==(const Scalar &q) const NOEXCEPT { return !!decaf_448_scalar_eq(s,q.s); } | |||
inline Point operator* (const Point &q) const NOEXCEPT { return q * (*this); } | |||
inline Point operator* (const Precomputed &q) const NOEXCEPT { return q * (*this); } | |||
}; | |||
class Point { | |||
@@ -105,6 +132,12 @@ public: | |||
inline Point& operator=(const Point &q) { decaf_448_point_copy(p,q.p); return *this; } | |||
inline ~Point() { decaf_448_point_destroy(p); } | |||
inline explicit Point(const std::string &s, decaf_bool_t allow_identity=DECAF_TRUE) throw(CryptoException) { | |||
if (!decode(*this,s,allow_identity)) throw CryptoException(); | |||
} | |||
inline explicit Point(const unsigned char buffer[DECAF_448_SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE) | |||
throw(CryptoException) { if (!decode(*this,buffer,allow_identity)) throw CryptoException(); } | |||
/* serialize / deserialize */ | |||
static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( | |||
Point &p, const unsigned char buffer[DECAF_448_SER_BYTES], decaf_bool_t allow_identity=DECAF_TRUE | |||
@@ -117,12 +150,31 @@ public: | |||
if (buffer.size() != DECAF_448_SER_BYTES) return DECAF_FAILURE; | |||
return decaf_448_point_decode(p.p,GET_DATA(buffer),allow_identity); | |||
} | |||
static inline Point from_hash_nonuniform ( const unsigned char buffer[DECAF_448_SER_BYTES] ) NOEXCEPT { | |||
Point p; decaf_448_point_from_hash_nonuniform(p.p,buffer); return p; | |||
} | |||
static inline Point from_hash_nonuniform ( const std::string &s ) NOEXCEPT { | |||
std::string t = s; | |||
if (t.size() < DECAF_448_SER_BYTES) t.insert(t.size(),DECAF_448_SER_BYTES-t.size(),0); | |||
Point p; decaf_448_point_from_hash_nonuniform(p.p,GET_DATA(t)); return p; | |||
} | |||
static inline Point from_hash ( const unsigned char buffer[2*DECAF_448_SER_BYTES] ) NOEXCEPT { | |||
Point p; decaf_448_point_from_hash_uniform(p.p,buffer); return p; | |||
} | |||
static inline Point from_hash ( const std::string &s ) NOEXCEPT { | |||
std::string t = s; | |||
if (t.size() < DECAF_448_SER_BYTES) return from_hash_nonuniform(s); | |||
if (t.size() < 2*DECAF_448_SER_BYTES) t.insert(t.size(),2*DECAF_448_SER_BYTES-t.size(),0); | |||
Point p; decaf_448_point_from_hash_uniform(p.p,GET_DATA(t)); return p; | |||
} | |||
inline EXPLICIT_CON operator std::string() const NOEXCEPT { | |||
unsigned char buffer[DECAF_448_SER_BYTES]; | |||
decaf_448_point_encode(buffer, p); | |||
return std::string((char*)buffer,sizeof(buffer)); | |||
} | |||
inline void write_to_buffer(unsigned char buffer[DECAF_448_SER_BYTES]) const NOEXCEPT{ | |||
inline void encode(unsigned char buffer[DECAF_448_SER_BYTES]) const NOEXCEPT{ | |||
decaf_448_point_encode(buffer, p); | |||
} | |||
@@ -134,11 +186,13 @@ public: | |||
inline Point operator- () const NOEXCEPT { Point r; decaf_448_point_negate(r.p,p); return r; } | |||
inline Point times_two () const NOEXCEPT { Point r; decaf_448_point_double(r.p,p); return r; } | |||
inline Point &double_in_place() NOEXCEPT { decaf_448_point_double(p,p); return *this; } | |||
inline bool operator!=(const Point &q) const NOEXCEPT { return ! decaf_448_point_eq(p,q.p); } | |||
inline bool operator==(const Point &q) const NOEXCEPT { return !!decaf_448_point_eq(p,q.p); } | |||
/* Scalarmul */ | |||
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_point_scalarmul(r.p,p,s.s); return r; } | |||
inline Point operator*=(const Scalar &s) NOEXCEPT { decaf_448_point_scalarmul(p,p,s.s); return *this; } | |||
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } | |||
static inline Point double_scalar_mul ( | |||
const Point &q, const Scalar &qs, const Point &r, const Scalar &rs | |||
@@ -147,8 +201,8 @@ public: | |||
} | |||
/* FIXME: are these defined to be correct? */ | |||
static inline const Point &base() NOEXCEPT { return (const Point &)decaf_448_point_base; } | |||
static inline const Point &identity() NOEXCEPT { return (const Point &)decaf_448_point_identity; } | |||
static inline const Point &base() NOEXCEPT { return *(const Point *)decaf_448_point_base; } | |||
static inline const Point &identity() NOEXCEPT { return *(const Point *)decaf_448_point_identity; } | |||
}; | |||
class Precomputed { | |||
@@ -181,8 +235,8 @@ private: | |||
public: | |||
inline ~Precomputed() NOEXCEPT { clear(); } | |||
inline Precomputed(const decaf_448_precomputed_s *yours = decaf_448_precomputed_base) NOEXCEPT { | |||
ours.yours = yours; | |||
inline Precomputed(const decaf_448_precomputed_s &yours = *decaf_448_precomputed_base) NOEXCEPT { | |||
ours.yours = &yours; | |||
isMine = false; | |||
} | |||
inline Precomputed &operator=(const Precomputed &it) { | |||
@@ -203,7 +257,8 @@ public: | |||
return *this; | |||
} | |||
inline Precomputed(const Precomputed &it) NOEXCEPT : isMine(false) { *this = it; } | |||
inline Precomputed(const Point &it) NOEXCEPT : isMine(false) { *this = it; } | |||
inline explicit Precomputed(const Point &it) NOEXCEPT : isMine(false) { *this = it; } | |||
#if __cplusplus >= 201103L | |||
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { | |||
if (this == &it) return *this; | |||
@@ -218,13 +273,14 @@ public: | |||
#endif | |||
inline Point operator* (const Scalar &s) const NOEXCEPT { Point r; decaf_448_precomputed_scalarmul(r.p,get(),s.s); return r; } | |||
inline Point operator/ (const Scalar &s) const NOEXCEPT { return (*this) * s.inverse(); } | |||
static inline const Precomputed base() NOEXCEPT { return Precomputed(decaf_448_precomputed_base); } | |||
static inline const Precomputed base() NOEXCEPT { return Precomputed(*decaf_448_precomputed_base); } | |||
}; | |||
#undef NOEXCEPT | |||
}; /* struct decaf<448> */ | |||
}; /* namespace decaf */ | |||
#undef NOEXCEPT | |||
} /* namespace decaf */ | |||
#endif /* __DECAF_448_HXX__ */ |
@@ -27,6 +27,10 @@ | |||
struct kparams_s; | |||
#endif | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/** | |||
* @brief Initialize a sponge context object. | |||
* @param [out] sponge The object to initialize. | |||
@@ -220,6 +224,10 @@ void spongerng_stir ( | |||
size_t len | |||
) API_VIS; | |||
#ifdef __cplusplus | |||
} /* extern "C" */ | |||
#endif | |||
#undef API_VIS | |||
#undef WARN_UNUSED | |||
@@ -678,7 +678,6 @@ void decaf_bzero ( | |||
void *s, | |||
size_t size | |||
) { | |||
if (s==NULL) return; | |||
#ifdef __STDC_LIB_EXT1__ | |||
memset_s(s, size, 0, size); | |||
#else | |||
@@ -720,7 +719,7 @@ void decaf_448_scalar_decode_long( | |||
decaf_448_scalar_decode_short(t1, &ser[i], ser_len-i); | |||
if (ser_len == sizeof(*ser)) { | |||
if (ser_len == sizeof(decaf_448_scalar_t)) { | |||
assert(i==0); | |||
/* ham-handed reduce */ | |||
decaf_448_montmul(s,t1,decaf_448_scalar_r1); | |||
@@ -0,0 +1,193 @@ | |||
/** | |||
* @file test_decaf.cxx | |||
* @author Mike Hamburg | |||
* | |||
* @copyright | |||
* Copyright (c) 2015 Cryptography Research, Inc. \n | |||
* Released under the MIT License. See LICENSE.txt for license information. | |||
* | |||
* @brief C++ tests, because that's easier. | |||
*/ | |||
#include "decaf.hxx" | |||
#include "shake.h" | |||
#include <stdio.h> | |||
typedef decaf::decaf<448>::Scalar Scalar; | |||
typedef decaf::decaf<448>::Point Point; | |||
typedef decaf::decaf<448>::Precomputed Precomputed; | |||
static const long NTESTS = 10000; | |||
static void print(const char *name, const Scalar &x) { | |||
unsigned char buffer[DECAF_448_SCALAR_BYTES]; | |||
x.encode(buffer); | |||
printf(" %s = 0x", name); | |||
for (int i=sizeof(buffer)-1; i>=0; i--) { | |||
printf("%02x", buffer[i]); | |||
} | |||
printf("\n"); | |||
} | |||
static void print(const char *name, const Point &x) { | |||
unsigned char buffer[DECAF_448_SER_BYTES]; | |||
x.encode(buffer); | |||
printf(" %s = 0x", name); | |||
for (int i=sizeof(buffer)-1; i>=0; i--) { | |||
printf("%02x", buffer[i]); | |||
} | |||
printf("\n"); | |||
} | |||
static bool passing = true; | |||
class Test { | |||
public: | |||
bool passing_now; | |||
Test(const char *test) { | |||
passing_now = true; | |||
printf("%s...", test); | |||
if (strlen(test) < 27) printf("%*s",int(27-strlen(test)),""); | |||
fflush(stdout); | |||
} | |||
~Test() { | |||
if (std::uncaught_exception()) { | |||
fail(); | |||
printf(" due to uncaught exception.\n"); | |||
} | |||
if (passing_now) printf("[PASS]\n"); | |||
} | |||
void fail() { | |||
if (!passing_now) return; | |||
passing_now = passing = false; | |||
printf("[FAIL]\n"); | |||
} | |||
}; | |||
static bool arith_check( | |||
Test &test, | |||
const Scalar &x, | |||
const Scalar &y, | |||
const Scalar &z, | |||
const Scalar &r, | |||
const Scalar &l, | |||
const char *name | |||
) { | |||
if (l == r) return true; | |||
test.fail(); | |||
printf(" %s", name); | |||
print("x", x); | |||
print("y", y); | |||
print("z", z); | |||
print("lhs", r); | |||
print("rhs", l); | |||
return false; | |||
} | |||
static bool point_check( | |||
Test &test, | |||
const Point &p, | |||
const Point &q, | |||
const Point &R, | |||
const Scalar &x, | |||
const Scalar &y, | |||
const Point &r, | |||
const Point &l, | |||
const char *name | |||
) { | |||
if (l == r) return true; | |||
test.fail(); | |||
printf(" %s", name); | |||
print("x", x); | |||
print("y", y); | |||
print("p", p); | |||
print("q", q); | |||
print("r", R); | |||
print("lhs", r); | |||
print("rhs", l); | |||
return false; | |||
} | |||
static void test_arithmetic() { | |||
keccak_sponge_t sponge; | |||
unsigned char buffer[DECAF_448_SCALAR_BYTES+8]; | |||
spongerng_init_from_buffer(sponge, (const uint8_t *)"test_arithmetic", 16, 1); | |||
Test test("Arithmetic"); | |||
Scalar x(0),y(0),z(0); | |||
arith_check(test,x,y,z,INT_MAX,(decaf_word_t)INT_MAX,"cast from max"); | |||
arith_check(test,x,y,z,INT_MIN,-Scalar(1+(decaf_word_t)INT_MAX),"cast from min"); | |||
for (int i=0; i<NTESTS*10 && test.passing_now; i++) { | |||
/* TODO: pathological cases */ | |||
size_t sob = sizeof(buffer) - (i%16); | |||
spongerng_next(sponge, buffer, sob); | |||
Scalar x(buffer, sob); | |||
spongerng_next(sponge, buffer, sob); | |||
Scalar y(buffer, sob); | |||
spongerng_next(sponge, buffer, sob); | |||
Scalar z(buffer, sob); | |||
arith_check(test,x,y,z,x+y,y+x,"commute add"); | |||
arith_check(test,x,y,z,x,x+0,"ident add"); | |||
arith_check(test,x,y,z,x,x-0,"ident sub"); | |||
arith_check(test,x,y,z,x+(y+z),(x+y)+z,"assoc add"); | |||
arith_check(test,x,y,z,x*(y+z),x*y + x*z,"distributive mul/add"); | |||
arith_check(test,x,y,z,x*(y-z),x*y - x*z,"distributive mul/add"); | |||
arith_check(test,x,y,z,x*(y*z),(x*y)*z,"assoc mul"); | |||
arith_check(test,x,y,z,x*y,y*x,"commute mul"); | |||
arith_check(test,x,y,z,x,x*1,"ident mul"); | |||
arith_check(test,x,y,z,0,x*0,"mul by 0"); | |||
arith_check(test,x,y,z,-x,x*-1,"mul by -1"); | |||
arith_check(test,x,y,z,x+x,x*2,"mul by 2"); | |||
if (i%20) continue; | |||
if (y!=0) arith_check(test,x,y,z,x*y/y,x,"invert"); | |||
arith_check(test,x,y,z,x/0,0,"invert0"); | |||
} | |||
} | |||
static void test_ec() { | |||
keccak_sponge_t sponge; | |||
unsigned char buffer[2*DECAF_448_SCALAR_BYTES]; | |||
spongerng_init_from_buffer(sponge, (const uint8_t *)"test_ec", 8, 1); | |||
Test test("EC"); | |||
for (int i=0; i<NTESTS && test.passing_now; i++) { | |||
/* TODO: pathological cases */ | |||
size_t sob = sizeof(buffer); | |||
spongerng_next(sponge, buffer, sob); | |||
Scalar x(buffer, sob); | |||
spongerng_next(sponge, buffer, sob); | |||
Scalar y(buffer, sob); | |||
spongerng_next(sponge, buffer, sob); | |||
Point p = Point::from_hash(buffer); | |||
spongerng_next(sponge, buffer, sob); | |||
Point q = Point::from_hash(buffer); | |||
spongerng_next(sponge, buffer, sob); | |||
Point r = Point::from_hash(buffer); | |||
point_check(test,p,q,r,0,0,p,Point((std::string)p),"round-trip"); | |||
point_check(test,p,q,r,0,0,p+q,q+p,"commute add"); | |||
point_check(test,p,q,r,0,0,p+(q+r),(p+q)+r,"assoc add"); | |||
if (i%10) continue; | |||
point_check(test,p,q,r,x,0,x*(p+q),x*p+x*q,"distr mul"); | |||
point_check(test,p,q,r,x,0,(x*y)*p,x*(y*p),"assoc mul"); | |||
point_check(test,p,q,r,x,0,Precomputed(p)*x,p*x,"precomp mul"); | |||
} | |||
} | |||
int main(int argc, char **argv) { | |||
(void) argc; (void) argv; | |||
test_arithmetic(); | |||
test_ec(); | |||
if (passing) printf("Passed all tests.\n"); | |||
return passing ? 0 : 1; | |||
} |