| @@ -66,7 +66,7 @@ CXXFLAGS = $(LANGXXFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENF | |||
| LDFLAGS = $(ARCHFLAGS) $(XLDFLAGS) | |||
| ASFLAGS = $(ARCHFLAGS) $(XASFLAGS) | |||
| .PHONY: clean all test bench todo doc lib bat | |||
| .PHONY: clean all test bench test_decaf bench_decaf todo doc lib bat | |||
| .PRECIOUS: build/%.s | |||
| HEADERS= Makefile $(shell find . -name "*.h") $(shell find . -name "*.hxx") build/timestamp | |||
| @@ -87,6 +87,7 @@ TESTCOMPONENTS=build/test.o build/test_scalarmul.o build/test_sha512.o \ | |||
| build/shake.o | |||
| TESTDECAFCOMPONENTS=build/test_decaf.o | |||
| BENCHDECAFCOMPONENTS=build/bench_decaf.o | |||
| BENCHCOMPONENTS = build/bench.o build/shake.o | |||
| @@ -108,7 +109,10 @@ build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) $(DECAFCOMPONENTS) | |||
| $(LD) $(LDFLAGS) -o $@ $^ -lgmp | |||
| build/test_decaf: $(TESTDECAFCOMPONENTS) decaf_lib | |||
| $(LDXX) $(LDFLAGS) -o $@ $< -lgmp -Lbuild -ldecaf | |||
| $(LDXX) $(LDFLAGS) -o $@ $< -Lbuild -Wl,-rpath=`pwd`/build -ldecaf | |||
| build/bench_decaf: $(BENCHDECAFCOMPONENTS) decaf_lib | |||
| $(LDXX) $(LDFLAGS) -o $@ $< -Lbuild -Wl,-rpath=`pwd`/build -ldecaf | |||
| build/shakesum: build/shakesum.o build/shake.o | |||
| $(LD) $(LDFLAGS) -o $@ $^ | |||
| @@ -223,7 +227,10 @@ test: build/test test_decaf | |||
| build/test | |||
| test_decaf: build/test_decaf | |||
| LD_LIBRARY_PATH=`pwd`/build:$(LD_LIBRARY_PATH) build/test_decaf | |||
| build/test_decaf | |||
| bench_decaf: build/bench_decaf | |||
| build/bench_decaf | |||
| clean: | |||
| rm -fr build doc $(BATNAME) | |||
| @@ -240,10 +240,10 @@ static inline void NONNULL2 decaf_448_scalar_copy ( | |||
| * @param [out] out Will become equal to a. | |||
| * @todo Make inline? | |||
| */ | |||
| void decaf_448_scalar_set API_VIS NONNULL1 ( | |||
| void decaf_448_scalar_set( | |||
| decaf_448_scalar_t out, | |||
| decaf_word_t a | |||
| ); | |||
| ) API_VIS NONNULL1; | |||
| /** | |||
| * @brief Encode a point as a sequence of bytes. | |||
| @@ -317,7 +317,7 @@ void decaf_448_point_add ( | |||
| decaf_448_point_t sum, | |||
| const decaf_448_point_t a, | |||
| const decaf_448_point_t b | |||
| ) API_VIS NONNULL3; // TODO: NOINLINE? | |||
| ) API_VIS NONNULL3; | |||
| /** | |||
| * @brief Double a point. Equivalent to | |||
| @@ -329,7 +329,7 @@ void decaf_448_point_add ( | |||
| void decaf_448_point_double ( | |||
| decaf_448_point_t two_a, | |||
| const decaf_448_point_t a | |||
| ) API_VIS NONNULL2; // TODO: NOINLINE? | |||
| ) API_VIS NONNULL2; | |||
| /** | |||
| * @brief Subtract two points to produce a third point. The | |||
| @@ -455,7 +455,7 @@ void decaf_448_point_double_scalarmul ( | |||
| * scaled = scalar1*decaf_448_point_base + scalar2*base2. | |||
| * | |||
| * Otherwise equivalent to decaf_448_point_double_scalarmul, but may be | |||
| * faster. | |||
| * faster at the expense of being variable time. | |||
| * | |||
| * @param [out] combo The linear combination scalar1*base + scalar2*base2. | |||
| * @param [in] scalar1 A first scalar to multiply by. | |||
| @@ -87,13 +87,13 @@ public: | |||
| decaf_448_scalar_t s; | |||
| /** @brief Set to an unsigned word */ | |||
| inline Scalar(const decaf_word_t w=0) NOEXCEPT { *this = w; } | |||
| inline Scalar(const decaf_word_t w) NOEXCEPT { *this = w; } | |||
| /** @brief Set to a signed word */ | |||
| inline Scalar(const int w) NOEXCEPT { *this = w; } | |||
| /** @brief Construct from decaf_scalar_t object. */ | |||
| inline Scalar(const decaf_448_scalar_t &t) NOEXCEPT { decaf_448_scalar_copy(s,t); } | |||
| inline Scalar(const decaf_448_scalar_t &t = decaf_448_scalar_zero) NOEXCEPT { decaf_448_scalar_copy(s,t); } | |||
| /** @brief Copy constructor. */ | |||
| inline Scalar(const Scalar &x) NOEXCEPT { decaf_448_scalar_copy(s,x.s); } | |||
| @@ -385,6 +385,15 @@ public: | |||
| Point p; decaf_448_point_double_scalarmul(p.p,q.p,qs.s,r.p,rs.s); return p; | |||
| } | |||
| /** | |||
| * @brief Double-scalar multiply: this point by the first scalar and base by the second scalar. | |||
| * @warning This function takes variable time, and may leak the scalars (or points, but currently | |||
| * it doesn't). | |||
| */ | |||
| inline Point non_secret_combo_with_base(const Scalar &s, const Scalar &s_base) { | |||
| Point r; decaf_448_base_double_scalarmul_non_secret(r.p,s_base.s,p,s.s); return r; | |||
| } | |||
| /** @brief Return the base point */ | |||
| static inline const Point base() NOEXCEPT { return Point(decaf_448_point_base); } | |||
| @@ -438,7 +447,8 @@ public: | |||
| * | |||
| * By default, initializes to the table for the base point. | |||
| * | |||
| * @todo: FIXME Harmonize with Point(), which initializes to the identity. | |||
| * @warning The empty initializer makes this equal to base, unlike the empty | |||
| * initializer for points which makes this equal to the identity. | |||
| */ | |||
| inline Precomputed( | |||
| const decaf_448_precomputed_s &yours = *decaf_448_precomputed_base | |||
| @@ -47,12 +47,10 @@ typedef struct { | |||
| /** x*Base */ | |||
| decaf_448_public_key_t pub; | |||
| /** @endcond */ | |||
| } | |||
| /** Private key structure for pointers. */ | |||
| decaf_448_private_key_s, | |||
| /** A private key (gmp array[1] style). */ | |||
| decaf_448_private_key_t[1]; | |||
| } /** Private key structure for pointers. */ | |||
| decaf_448_private_key_s, | |||
| /** A private key (gmp array[1] style). */ | |||
| decaf_448_private_key_t[1]; | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| @@ -179,7 +177,7 @@ decaf_448_verify ( | |||
| #undef NONNULL5 | |||
| #ifdef __cplusplus | |||
| }; /* extern "C" */ | |||
| } /* extern "C" */ | |||
| #endif | |||
| #endif /* __DECAF_CRYPTO_H__ */ | |||
| @@ -0,0 +1,145 @@ | |||
| /** | |||
| * @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++ benchmarks, because that's easier. | |||
| */ | |||
| #include "decaf.hxx" | |||
| #include "shake.h" | |||
| #include "decaf_crypto.h" | |||
| #include <stdio.h> | |||
| #include <sys/time.h> | |||
| #include <assert.h> | |||
| #include <stdint.h> | |||
| typedef decaf::decaf<448>::Scalar Scalar; | |||
| typedef decaf::decaf<448>::Point Point; | |||
| typedef decaf::decaf<448>::Precomputed Precomputed; | |||
| static __inline__ void __attribute__((unused)) ignore_result ( int result ) { (void)result; } | |||
| static double now(void) { | |||
| struct timeval tv; | |||
| gettimeofday(&tv, NULL); | |||
| return tv.tv_sec + tv.tv_usec/1000000.0; | |||
| } | |||
| // RDTSC from the chacha code | |||
| #ifndef __has_builtin | |||
| #define __has_builtin(X) 0 | |||
| #endif | |||
| #if defined(__clang__) && __has_builtin(__builtin_readcyclecounter) | |||
| #define rdtsc __builtin_readcyclecounter | |||
| #else | |||
| static inline uint64_t rdtsc(void) { | |||
| u_int64_t out = 0; | |||
| # if (defined(__i386__) || defined(__x86_64__)) | |||
| __asm__ __volatile__ ("rdtsc" : "=A"(out)); | |||
| # endif | |||
| return out; | |||
| } | |||
| #endif | |||
| class Benchmark { | |||
| static const int NTESTS = 1000; | |||
| public: | |||
| int i, ntests; | |||
| double begin; | |||
| uint64_t tsc_begin; | |||
| Benchmark(const char *s, double factor = 1) { | |||
| printf("%s:", s); | |||
| if (strlen(s) < 25) printf("%*s",int(25-strlen(s)),""); | |||
| fflush(stdout); | |||
| i = 0; | |||
| ntests = NTESTS * factor; | |||
| begin = now(); | |||
| tsc_begin = rdtsc(); | |||
| } | |||
| ~Benchmark() { | |||
| double tsc = (rdtsc() - tsc_begin) * 1.0 / ntests; | |||
| double t = (now() - begin)/ntests; | |||
| const char *small[] = {" ","m","µ","n","p"}; | |||
| const char *big[] = {" ","k","M","G","T"}; | |||
| unsigned di=0; | |||
| for (di=0; di<sizeof(small)/sizeof(*small)-1 && t && t < 1; di++) { | |||
| t *= 1000.0; | |||
| } | |||
| unsigned bi=0; | |||
| for (bi=0; bi<sizeof(big)/sizeof(*big)-1 && tsc && tsc >= 1000; bi++) { | |||
| tsc /= 1000.0; | |||
| } | |||
| printf("%7.2f %ss", t, small[di]); | |||
| if (tsc) printf(" %7.2f %scy", tsc, big[bi]); | |||
| printf("\n"); | |||
| } | |||
| inline bool iter() { return i++ < ntests; } | |||
| }; | |||
| int main(int argc, char **argv) { | |||
| bool micro = false; | |||
| if (argc >= 2 && !strcmp(argv[1], "--micro")) | |||
| micro = true; | |||
| decaf_448_public_key_t p1,p2; | |||
| decaf_448_private_key_t s1,s2; | |||
| decaf_448_symmetric_key_t r1,r2; | |||
| decaf_448_signature_t sig1; | |||
| unsigned char ss[32]; | |||
| memset(r1,1,sizeof(r1)); | |||
| memset(r2,2,sizeof(r2)); | |||
| unsigned char umessage[] = {1,2,3,4,5}; | |||
| size_t lmessage = sizeof(umessage); | |||
| if (micro) { | |||
| Precomputed pBase; | |||
| Point p,q; | |||
| Scalar s,t; | |||
| printf("Micro:\n"); | |||
| for (Benchmark b("Scalar add", 1000); b.iter(); ) { s+t; } | |||
| for (Benchmark b("Scalar times", 100); b.iter(); ) { s*t; } | |||
| for (Benchmark b("Scalar inv", 10); b.iter(); ) { s.inverse(); } | |||
| for (Benchmark b("Point add", 100); b.iter(); ) { p + q; } | |||
| for (Benchmark b("Point double", 100); b.iter(); ) { p.double_in_place(); } | |||
| for (Benchmark b("Point scalarmul"); b.iter(); ) { p * s; } | |||
| for (Benchmark b("Point double scalarmul"); b.iter(); ) { Point::double_scalarmul(p,s,q,t); } | |||
| for (Benchmark b("Point precmp scalarmul"); b.iter(); ) { pBase * s; } | |||
| /* TODO: scalarmul for verif */ | |||
| printf("\nMacro:\n"); | |||
| } | |||
| for (Benchmark b("Keygen"); b.iter(); ) { | |||
| decaf_448_derive_private_key(s1,r1); | |||
| } | |||
| decaf_448_private_to_public(p1,s1); | |||
| decaf_448_derive_private_key(s2,r2); | |||
| decaf_448_private_to_public(p2,s2); | |||
| for (Benchmark b("Shared secret"); b.iter(); ) { | |||
| decaf_bool_t ret = decaf_448_shared_secret(ss,sizeof(ss),s1,p2); | |||
| ignore_result(ret); | |||
| assert(ret); | |||
| } | |||
| for (Benchmark b("Sign"); b.iter(); ) { | |||
| decaf_448_sign(sig1,s1,umessage,lmessage); | |||
| } | |||
| for (Benchmark b("Verify"); b.iter(); ) { | |||
| decaf_bool_t ret = decaf_448_verify(sig1,p1,umessage,lmessage); | |||
| umessage[0]++; | |||
| ignore_result(ret); | |||
| } | |||
| printf("\n"); | |||
| return 0; | |||
| } | |||
| @@ -157,7 +157,7 @@ static void test_ec() { | |||
| Test test("EC"); | |||
| Point id; | |||
| Point id = Point::identity(), base = Point::base(); | |||
| point_check(test,id,id,id,0,0,Point::from_hash(std::string("")),id,"fh0"); | |||
| point_check(test,id,id,id,0,0,Point::from_hash(std::string("\x01")),id,"fh1"); | |||
| @@ -183,6 +183,7 @@ static void test_ec() { | |||
| point_check(test,p,q,r,x,0,x*(p+q),x*p+x*q,"distr mul"); | |||
| point_check(test,p,q,r,x,y,(x*y)*p,x*(y*p),"assoc mul"); | |||
| point_check(test,p,q,r,x,y,x*p+y*q,Point::double_scalarmul(x,p,y,q),"ds mul"); | |||
| point_check(test,base,q,r,x,y,x*base+y*q,q.non_secret_combo_with_base(y,x),"ds vt mul"); | |||
| point_check(test,p,q,r,x,0,Precomputed(p)*x,p*x,"precomp mul"); | |||
| } | |||
| } | |||