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