@@ -7,10 +7,13 @@ MACHINE := $(shell uname -m) | |||||
ifeq ($(UNAME),Darwin) | ifeq ($(UNAME),Darwin) | ||||
CC = clang | CC = clang | ||||
CXX = clang++ | |||||
else | else | ||||
CC = gcc | CC = gcc | ||||
CXX = g++ | |||||
endif | endif | ||||
LD = $(CC) | LD = $(CC) | ||||
LDXX = $(CXX) | |||||
ASM ?= $(CC) | ASM ?= $(CC) | ||||
DECAF ?= decaf | DECAF ?= decaf | ||||
@@ -30,6 +33,7 @@ WARNFLAGS = -pedantic -Wall -Wextra -Werror -Wunreachable-code \ | |||||
INCFLAGS = -Isrc/include -Iinclude -Isrc/$(FIELD) -Isrc/$(FIELD)/$(ARCH) | INCFLAGS = -Isrc/include -Iinclude -Isrc/$(FIELD) -Isrc/$(FIELD)/$(ARCH) | ||||
LANGFLAGS = -std=c99 -fno-strict-aliasing | LANGFLAGS = -std=c99 -fno-strict-aliasing | ||||
LANGXXFLAGS = -fno-strict-aliasing | |||||
GENFLAGS = -ffunction-sections -fdata-sections -fvisibility=hidden -fomit-frame-pointer -fPIC | GENFLAGS = -ffunction-sections -fdata-sections -fvisibility=hidden -fomit-frame-pointer -fPIC | ||||
OFLAGS = -O3 | OFLAGS = -O3 | ||||
@@ -58,6 +62,7 @@ endif | |||||
ARCHFLAGS += $(XARCHFLAGS) | ARCHFLAGS += $(XARCHFLAGS) | ||||
CFLAGS = $(LANGFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCFLAGS) | CFLAGS = $(LANGFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCFLAGS) | ||||
CXXFLAGS = $(LANGXXFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCXXFLAGS) | |||||
LDFLAGS = $(ARCHFLAGS) $(XLDFLAGS) | LDFLAGS = $(ARCHFLAGS) $(XLDFLAGS) | ||||
ASFLAGS = $(ARCHFLAGS) $(XASFLAGS) | 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/test_pointops.o build/test_arithmetic.o build/test_goldilocks.o build/magic.o \ | ||||
build/shake.o | build/shake.o | ||||
TESTDECAFCOMPONENTS=build/test_decaf.o | |||||
BENCHCOMPONENTS = build/bench.o build/shake.o | BENCHCOMPONENTS = build/bench.o build/shake.o | ||||
BATBASE=ed448goldilocks-bats-$(TODAY) | BATBASE=ed448goldilocks-bats-$(TODAY) | ||||
@@ -92,42 +99,45 @@ scan: clean | |||||
scan-build --use-analyzer=`which clang` \ | scan-build --use-analyzer=`which clang` \ | ||||
-enable-checker deadcode -enable-checker llvm \ | -enable-checker deadcode -enable-checker llvm \ | ||||
-enable-checker osx -enable-checker security -enable-checker unix \ | -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) | build/bench: $(LIBCOMPONENTS) $(BENCHCOMPONENTS) $(DECAFCOMPONENTS) | ||||
$(LD) $(LDFLAGS) -o $@ $^ | $(LD) $(LDFLAGS) -o $@ $^ | ||||
build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) $(DECAFCOMPONENTS) | build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) $(DECAFCOMPONENTS) | ||||
$(LD) $(LDFLAGS) -o $@ $^ -lgmp | $(LD) $(LDFLAGS) -o $@ $^ -lgmp | ||||
build/test_decaf: $(TESTDECAFCOMPONENTS) decaf_lib | |||||
$(LDXX) $(LDFLAGS) -o $@ $< -lgmp -Lbuild -ldecaf | |||||
build/shakesum: build/shakesum.o build/shake.o | build/shakesum: build/shakesum.o build/shake.o | ||||
$(LD) $(LDFLAGS) -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 $@ | rm -f $@ | ||||
ifeq ($(UNAME),Darwin) | ifeq ($(UNAME),Darwin) | ||||
libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ | libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ | ||||
$(LIBCOMPONENTS) | $(LIBCOMPONENTS) | ||||
else | 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 $@ | strip --discard-all $@ | ||||
ln -sf `basename $@` build/goldilocks.so.1 | |||||
ln -sf `basename $@` build/libgoldilocks.so.1 | |||||
endif | endif | ||||
build/decaf.so: $(DECAFCOMPONENTS) | |||||
build/libdecaf.so: $(DECAFCOMPONENTS) | |||||
rm -f $@ | rm -f $@ | ||||
ifeq ($(UNAME),Darwin) | ifeq ($(UNAME),Darwin) | ||||
libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ | libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ | ||||
$(DECAFCOMPONENTS) | $(DECAFCOMPONENTS) | ||||
else | 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 $@ | strip --discard-all $@ | ||||
ln -sf `basename $@` build/goldilocks.so.1 | |||||
ln -sf `basename $@` build/libdecaf.so.1 | |||||
endif | endif | ||||
build/timestamp: | build/timestamp: | ||||
@@ -148,10 +158,16 @@ build/decaf_tables.s: build/decaf_tables.c $(HEADERS) | |||||
build/%.s: src/%.c $(HEADERS) | build/%.s: src/%.c $(HEADERS) | ||||
$(CC) $(CFLAGS) -S -c -o $@ $< | $(CC) $(CFLAGS) -S -c -o $@ $< | ||||
build/%.s: src/%.cxx $(HEADERS) | |||||
$(CXX) $(CXXFLAGS) -S -c -o $@ $< | |||||
build/%.s: test/%.c $(HEADERS) | build/%.s: test/%.c $(HEADERS) | ||||
$(CC) $(CFLAGS) -S -c -o $@ $< | $(CC) $(CFLAGS) -S -c -o $@ $< | ||||
build/%.s: test/%.cxx $(HEADERS) | |||||
$(CXX) $(CXXFLAGS) -S -c -o $@ $< | |||||
build/%.s: src/$(FIELD)/$(ARCH)/%.c $(HEADERS) | build/%.s: src/$(FIELD)/$(ARCH)/%.c $(HEADERS) | ||||
$(CC) $(CFLAGS) -S -c -o $@ $< | $(CC) $(CFLAGS) -S -c -o $@ $< | ||||
@@ -203,8 +219,11 @@ todo:: | |||||
bench: build/bench | 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: | clean: | ||||
rm -fr build doc $(BATNAME) | rm -fr build doc $(BATNAME) |
@@ -76,7 +76,7 @@ struct decaf_448_precomputed_s; | |||||
typedef struct decaf_448_precomputed_s decaf_448_precomputed_s; | typedef struct decaf_448_precomputed_s decaf_448_precomputed_s; | ||||
/** Size and alignment of precomputed point tables. */ | /** 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. */ | /** Scalar is stored packed, because we don't need the speed. */ | ||||
typedef struct decaf_448_scalar_s { | 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. | * @brief Overwrite data with zeros. Uses memset_s if available. | ||||
* If data is NULL, this function has no effect. | |||||
*/ | */ | ||||
void decaf_bzero ( | void decaf_bzero ( | ||||
void *data, | void *data, | ||||
@@ -562,7 +561,7 @@ void decaf_448_precomputed_destroy ( | |||||
#undef NONNULL5 | #undef NONNULL5 | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
}; /* extern "C" */ | |||||
} /* extern "C" */ | |||||
#endif | #endif | ||||
#endif /* __DECAF_448_H__ */ | #endif /* __DECAF_448_H__ */ |
@@ -28,6 +28,8 @@ | |||||
#include "decaf.h" | #include "decaf.h" | ||||
#include <string> | #include <string> | ||||
#include <sys/types.h> | |||||
#include <limits.h> | |||||
/* TODO: document */ | /* TODO: document */ | ||||
/* TODO: This is incomplete */ | /* TODO: This is incomplete */ | ||||
@@ -38,7 +40,7 @@ | |||||
#define EXPLICIT_CON explicit | #define EXPLICIT_CON explicit | ||||
#define GET_DATA(str) ((const unsigned char *)&(str)[0]) | #define GET_DATA(str) ((const unsigned char *)&(str)[0]) | ||||
#else | #else | ||||
#define NOEXCEPT | |||||
#define NOEXCEPT throw() | |||||
#define EXPLICIT_CON | #define EXPLICIT_CON | ||||
#define GET_DATA(str) ((const unsigned char *)((str).data())) | #define GET_DATA(str) ((const unsigned char *)((str).data())) | ||||
#endif | #endif | ||||
@@ -50,18 +52,36 @@ void really_bzero(void *data, size_t size); | |||||
template<unsigned int bits = 448> struct decaf; | template<unsigned int bits = 448> struct decaf; | ||||
template<> struct decaf<448> { | 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 { | class Scalar { | ||||
public: | public: | ||||
decaf_448_scalar_t s; | decaf_448_scalar_t s; | ||||
inline Scalar() NOEXCEPT {} | inline Scalar() NOEXCEPT {} | ||||
inline Scalar(const decaf_word_t w) NOEXCEPT { decaf_448_scalar_set(s,w); } | 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 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(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& operator=(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); return *this; } | ||||
inline ~Scalar() NOEXCEPT { decaf_448_scalar_destroy(s); } | inline ~Scalar() NOEXCEPT { decaf_448_scalar_destroy(s); } | ||||
/* Initialize from buffer */ | /* 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 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 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); } | 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); | decaf_448_scalar_encode(buffer, s); | ||||
return std::string((char*)buffer,sizeof(buffer)); | 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); | 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) 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) 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 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 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 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 { | class Point { | ||||
@@ -105,6 +132,12 @@ public: | |||||
inline Point& operator=(const Point &q) { decaf_448_point_copy(p,q.p); return *this; } | inline Point& operator=(const Point &q) { decaf_448_point_copy(p,q.p); return *this; } | ||||
inline ~Point() { decaf_448_point_destroy(p); } | 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 */ | /* serialize / deserialize */ | ||||
static inline decaf_bool_t __attribute__((warn_unused_result)) decode ( | 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 | 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; | if (buffer.size() != DECAF_448_SER_BYTES) return DECAF_FAILURE; | ||||
return decaf_448_point_decode(p.p,GET_DATA(buffer),allow_identity); | 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 { | inline EXPLICIT_CON operator std::string() const NOEXCEPT { | ||||
unsigned char buffer[DECAF_448_SER_BYTES]; | unsigned char buffer[DECAF_448_SER_BYTES]; | ||||
decaf_448_point_encode(buffer, p); | decaf_448_point_encode(buffer, p); | ||||
return std::string((char*)buffer,sizeof(buffer)); | 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); | 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 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 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 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); } | inline bool operator==(const Point &q) const NOEXCEPT { return !!decaf_448_point_eq(p,q.p); } | ||||
/* Scalarmul */ | /* 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) 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) 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 ( | static inline Point double_scalar_mul ( | ||||
const Point &q, const Scalar &qs, const Point &r, const Scalar &rs | const Point &q, const Scalar &qs, const Point &r, const Scalar &rs | ||||
@@ -147,8 +201,8 @@ public: | |||||
} | } | ||||
/* FIXME: are these defined to be correct? */ | /* 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 { | class Precomputed { | ||||
@@ -181,8 +235,8 @@ private: | |||||
public: | public: | ||||
inline ~Precomputed() NOEXCEPT { clear(); } | 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; | isMine = false; | ||||
} | } | ||||
inline Precomputed &operator=(const Precomputed &it) { | inline Precomputed &operator=(const Precomputed &it) { | ||||
@@ -203,7 +257,8 @@ public: | |||||
return *this; | return *this; | ||||
} | } | ||||
inline Precomputed(const Precomputed &it) NOEXCEPT : isMine(false) { *this = it; } | 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 | #if __cplusplus >= 201103L | ||||
inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { | inline Precomputed &operator=(Precomputed &&it) NOEXCEPT { | ||||
if (this == &it) return *this; | if (this == &it) return *this; | ||||
@@ -218,13 +273,14 @@ public: | |||||
#endif | #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 { 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> */ | }; /* struct decaf<448> */ | ||||
}; /* namespace decaf */ | |||||
#undef NOEXCEPT | |||||
} /* namespace decaf */ | |||||
#endif /* __DECAF_448_HXX__ */ | #endif /* __DECAF_448_HXX__ */ |
@@ -27,6 +27,10 @@ | |||||
struct kparams_s; | struct kparams_s; | ||||
#endif | #endif | ||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/** | /** | ||||
* @brief Initialize a sponge context object. | * @brief Initialize a sponge context object. | ||||
* @param [out] sponge The object to initialize. | * @param [out] sponge The object to initialize. | ||||
@@ -220,6 +224,10 @@ void spongerng_stir ( | |||||
size_t len | size_t len | ||||
) API_VIS; | ) API_VIS; | ||||
#ifdef __cplusplus | |||||
} /* extern "C" */ | |||||
#endif | |||||
#undef API_VIS | #undef API_VIS | ||||
#undef WARN_UNUSED | #undef WARN_UNUSED | ||||
@@ -678,7 +678,6 @@ void decaf_bzero ( | |||||
void *s, | void *s, | ||||
size_t size | size_t size | ||||
) { | ) { | ||||
if (s==NULL) return; | |||||
#ifdef __STDC_LIB_EXT1__ | #ifdef __STDC_LIB_EXT1__ | ||||
memset_s(s, size, 0, size); | memset_s(s, size, 0, size); | ||||
#else | #else | ||||
@@ -720,7 +719,7 @@ void decaf_448_scalar_decode_long( | |||||
decaf_448_scalar_decode_short(t1, &ser[i], ser_len-i); | 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); | assert(i==0); | ||||
/* ham-handed reduce */ | /* ham-handed reduce */ | ||||
decaf_448_montmul(s,t1,decaf_448_scalar_r1); | 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; | |||||
} |