| @@ -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; | |||
| } | |||