From d35124f304bd3e497e0f29abd30fe0cbda6bcd40 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Fri, 14 Dec 2018 03:17:04 -0500 Subject: [PATCH] Make SSE2 configurable via CRYPTOPP_SSE2_INTRIN_AVAILABLE Benchmarking shows things run a little slower with SSE2 on modern Core i5's. Also update comments and links --- bench1.cpp | 4 ++-- donna.h | 24 +++++++++++++++++++++--- donna_32.cpp | 11 ++++------- donna_64.cpp | 6 +++--- donna_sse.cpp | 21 ++++++++++++++------- 5 files changed, 44 insertions(+), 22 deletions(-) diff --git a/bench1.cpp b/bench1.cpp index 82014aaa..4398fa9f 100644 --- a/bench1.cpp +++ b/bench1.cpp @@ -122,13 +122,13 @@ void OutputResultOperations(const char *name, const char *provider, const char * oss << "\n" << name << " " << operation << (pc ? " with precomputation" : ""); //oss << "" << provider; - oss << "" << std::setprecision(4) << std::setiosflags(std::ios::fixed) << (1000*timeTaken/iterations); + oss << "" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*timeTaken/iterations); // Coverity finding if (g_hertz > 1.0f) { const double t = timeTaken * g_hertz / iterations / 1000000; - oss << "" << std::setprecision(4) << std::setiosflags(std::ios::fixed) << t; + oss << "" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << t; } g_logTotal += log(iterations/timeTaken); diff --git a/donna.h b/donna.h index bc7fdc19..2c0f3ea8 100644 --- a/donna.h +++ b/donna.h @@ -1,6 +1,12 @@ // donna.h - written and placed in public domain by Jeffrey Walton -// This is a port of Adam Langley's curve25519-donna -// located at https://github.com/agl/curve25519-donna +// This is a integration of Andrew Moon's public domain code. +// Also see https://github.com/floodyberry/curve25519-donna. + +// Benchmarking on a modern Core i5-6400 shows SSE2 on Linux is not +// profitable. You can enable it with CRYPTOPP_CURVE25519_SSE2. + +// If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", +// https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 #ifndef CRYPTOPP_DONNA_H #define CRYPTOPP_DONNA_H @@ -39,7 +45,19 @@ int curve25519(byte sharedKey[32], const byte secretKey[32], const byte othersKe # define CRYPTOPP_CURVE25519_64BIT 1 #endif -#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +// Benchmarking on a modern Core i5-6400 shows SSE2 on Linux is +// not profitable. Here are the numbers in milliseconds/operation: +// +// * Langley, C++, 0.050 +// * Moon, C++: 0.040 +// * Moon, SSE2: 0.061 +// * Moon, native: 0.045 + +#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) && 0 +# define CRYPTOPP_CURVE25519_SSE2 1 +#endif + +#if (CRYPTOPP_CURVE25519_SSE2) extern int curve25519_SSE2(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]); #endif diff --git a/donna_32.cpp b/donna_32.cpp index 80b04d41..ce4fe057 100644 --- a/donna_32.cpp +++ b/donna_32.cpp @@ -1,6 +1,6 @@ // donna_32.cpp - written and placed in public domain by Jeffrey Walton // This is a integration of Andrew Moon's public domain code. -// Also see curve25519-donna-32bit.h. +// Also see https://github.com/floodyberry/curve25519-donna. // If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", // https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 @@ -448,10 +448,7 @@ int curve25519_CXX(byte sharedKey[32], const byte secretKey[32], const byte othe FixedSizeSecBlock e; for (size_t i = 0;i < 32;++i) e[i] = secretKey[i]; - - e[ 0] &= 0xf8; - e[31] &= 0x7f; - e[31] |= 0x40; + e[0] &= 0xf8; e[31] &= 0x7f; e[31] |= 0x40; bignum25519 nqpqx = {1}, nqpqz = {0}, nqz = {1}, nqx; bignum25519 q, qx, qpqx, qqx, zzz, zmone; @@ -513,7 +510,7 @@ int curve25519_CXX(byte sharedKey[32], const byte secretKey[32], const byte othe int curve25519(byte publicKey[32], const byte secretKey[32]) { -#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +#if (CRYPTOPP_CURVE25519_SSE2) if (HasSSE2()) return curve25519_SSE2(publicKey, secretKey, basePoint); else @@ -524,7 +521,7 @@ int curve25519(byte publicKey[32], const byte secretKey[32]) int curve25519(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]) { -#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +#if (CRYPTOPP_CURVE25519_SSE2) if (HasSSE2()) return curve25519_SSE2(sharedKey, secretKey, othersKey); else diff --git a/donna_64.cpp b/donna_64.cpp index 92ccf390..810ee01f 100644 --- a/donna_64.cpp +++ b/donna_64.cpp @@ -1,6 +1,6 @@ // donna_64.cpp - written and placed in public domain by Jeffrey Walton // This is a integration of Andrew Moon's public domain code. -// Also see curve25519-donna-64bit.h. +// Also see https://github.com/floodyberry/curve25519-donna. // If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", // https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 @@ -442,7 +442,7 @@ int curve25519_CXX(byte sharedKey[32], const byte secretKey[32], const byte othe int curve25519(byte publicKey[32], const byte secretKey[32]) { -#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +#if (CRYPTOPP_CURVE25519_SSE2) if (HasSSE2()) return curve25519_SSE2(publicKey, secretKey, basePoint); else @@ -453,7 +453,7 @@ int curve25519(byte publicKey[32], const byte secretKey[32]) int curve25519(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32]) { -#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +#if (CRYPTOPP_CURVE25519_SSE2) if (HasSSE2()) return curve25519_SSE2(sharedKey, secretKey, othersKey); else diff --git a/donna_sse.cpp b/donna_sse.cpp index 65dab78a..c6e926d8 100644 --- a/donna_sse.cpp +++ b/donna_sse.cpp @@ -1,13 +1,14 @@ // donna_sse.cpp - written and placed in public domain by Jeffrey Walton -// This is an integration of Andrew Moon's public domain code. -// Also see curve25519-donna-sse2.h. +// This is a integration of Andrew Moon's public domain code. +// Also see https://github.com/floodyberry/curve25519-donna. // This is a integration of Andrew Moon's public domain code. The port was // clean, but it has one potential problem. The original code is C and relies // upon unions. Accessing the inactive union member is undefined behavior in // C++. That means copying the array into packedelem8.u is OK; but then using -// packedelem8.v in a calcualtion is undefined behavior. We will have to -// keep an eye on things or rewrite significant portions of this code. +// packedelem8.v in a calcualtion is UB. Fortunately most (all?) compilers +// take pity on C++ developers and compile the code. We will have to keep an +// eye on things or rewrite significant portions of this code. // If needed, see Moon's commit "Go back to ignoring 256th bit [sic]", // https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658 @@ -19,14 +20,20 @@ #include "secblock.h" #include "misc.h" -#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +#if (CRYPTOPP_CURVE25519_SSE2) # include #endif +// The data is aligned, but Clang issues warning based on type +// and not the actual alignment of the variable and data. +#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE +# pragma GCC diagnostic ignored "-Wcast-align" +#endif + // Squash MS LNK4221 and libtool warnings extern const char DONNA_SSE_FNAME[] = __FILE__; -#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE) +#if (CRYPTOPP_CURVE25519_SSE2) typedef __m128i xmmi; #define ALIGN(n) CRYPTOPP_ALIGN_DATA(n) @@ -1164,4 +1171,4 @@ int curve25519_SSE2(byte sharedKey[32], const byte secretKey[32], const byte oth NAMESPACE_END // Donna NAMESPACE_END // CryptoPP -#endif // CRYPTOPP_SSE2_INTRIN_AVAILABLE +#endif // CRYPTOPP_CURVE25519_SSE2