Cherry-pick some commits from Crypto++ to make OpenMP for scrypt work on Windows

This commit is contained in:
Sebastian Messmer 2019-01-21 03:38:20 -08:00
parent db6ed6ec99
commit 38397a2d86
5 changed files with 38 additions and 5 deletions

5
vendor/README vendored
View File

@ -5,3 +5,8 @@ spdlog: https://github.com/gabime/spdlog/tree/v0.16.3/include/spdlog
cryptopp: https://github.com/weidai11/cryptopp/tree/CRYPTOPP_8_0_0 cryptopp: https://github.com/weidai11/cryptopp/tree/CRYPTOPP_8_0_0
- changed: added CMakeLists.txt and cryptopp-config.cmake from https://github.com/noloader/cryptopp-cmake/tree/CRYPTOPP_8_0_0 - changed: added CMakeLists.txt and cryptopp-config.cmake from https://github.com/noloader/cryptopp-cmake/tree/CRYPTOPP_8_0_0
- changed: commented out line including winapifamily.h in CMakeLists.txt - changed: commented out line including winapifamily.h in CMakeLists.txt
- cherry-picked commits to get OpenMP for scrypt on Windows:
- https://github.com/weidai11/cryptopp/commit/aa043b38a7930725c31a0cd7016986d1c581c573
- https://github.com/weidai11/cryptopp/commit/672f5c7f3dad8ae12b2d0ce0940ccb7c8e257bf8
- https://github.com/weidai11/cryptopp/commit/7e96a283a3192d29aac5b60e5b4ff19248f00d9a
- https://github.com/weidai11/cryptopp/commit/ca32b63038d5f7b13e2e00809cd9184a1efe8c24

View File

@ -139,6 +139,7 @@ LDLIBS =
# CXXFLAGS = $(CXXFLAGS) /DDEBUG /D_DEBUG /Oi /Oy- /Od /MTd # CXXFLAGS = $(CXXFLAGS) /DDEBUG /D_DEBUG /Oi /Oy- /Od /MTd
# Release build. Add /OPT:REF to linker # Release build. Add /OPT:REF to linker
CXXFLAGS = $(CXXFLAGS) /DNDEBUG /D_NDEBUG /Oi /Oy /O2 /MT CXXFLAGS = $(CXXFLAGS) /DNDEBUG /D_NDEBUG /Oi /Oy /O2 /MT
# Linker flags.
LDFLAGS = $(LDFLAGS) /OPT:REF LDFLAGS = $(LDFLAGS) /OPT:REF
# Attempt to detect when <sdkddkver.h> and <winapifamily.h> are available # Attempt to detect when <sdkddkver.h> and <winapifamily.h> are available

View File

@ -90,9 +90,14 @@ void Salsa20_Core(word32* data, unsigned int rounds)
x[15] ^= rotlConstant<18>(x[14]+x[13]); x[15] ^= rotlConstant<18>(x[14]+x[13]);
} }
#ifdef _MSC_VER
for (size_t i = 0; i < 16; ++i)
data[i] += x[i];
#else
#pragma omp simd #pragma omp simd
for (size_t i = 0; i < 16; ++i) for (size_t i = 0; i < 16; ++i)
data[i] += x[i]; data[i] += x[i];
#endif
} }
std::string Salsa20_Policy::AlgorithmProvider() const std::string Salsa20_Policy::AlgorithmProvider() const

View File

@ -14,6 +14,8 @@
#include "sha.h" #include "sha.h"
#include <sstream> #include <sstream>
#include <limits>
#ifdef _OPENMP #ifdef _OPENMP
# include <omp.h> # include <omp.h>
#endif #endif
@ -53,9 +55,14 @@ static inline void BlockCopy(byte* dest, byte* src, size_t len)
static inline void BlockXOR(byte* dest, byte* src, size_t len) static inline void BlockXOR(byte* dest, byte* src, size_t len)
{ {
#ifdef _MSC_VER
for (size_t i = 0; i < len; ++i)
dest[i] ^= src[i];
#else
#pragma omp simd #pragma omp simd
for (size_t i = 0; i < len; ++i) for (size_t i = 0; i < len; ++i)
dest[i] ^= src[i]; dest[i] ^= src[i];
#endif
} }
static inline void PBKDF2_SHA256(byte* buf, size_t dkLen, static inline void PBKDF2_SHA256(byte* buf, size_t dkLen,
@ -171,6 +178,16 @@ void Scrypt::ValidateParameters(size_t derivedLen, word64 cost, word64 blockSize
} }
} }
// https://github.com/weidai11/cryptopp/issues/787
CRYPTOPP_ASSERT(parallelization <= std::numeric_limits<int>::max());
if (parallelization > static_cast<word64>(std::numeric_limits<int>::max()))
{
std::ostringstream oss;
oss << " parallelization " << parallelization << " is larger than ";
oss << std::numeric_limits<int>::max();
throw InvalidArgument("Scrypt: " + oss.str());
}
CRYPTOPP_ASSERT(IsPowerOf2(cost)); CRYPTOPP_ASSERT(IsPowerOf2(cost));
if (IsPowerOf2(cost) == false) if (IsPowerOf2(cost) == false)
throw InvalidArgument("Scrypt: cost must be a power of 2"); throw InvalidArgument("Scrypt: cost must be a power of 2");
@ -245,10 +262,13 @@ size_t Scrypt::DeriveKey(byte*derived, size_t derivedLen, const byte*secret, siz
// 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) // 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen)
PBKDF2_SHA256(B, B.size(), secret, secretLen, salt, saltLen, 1); PBKDF2_SHA256(B, B.size(), secret, secretLen, salt, saltLen, 1);
// Visual Studio and OpenMP 2.0 fixup. We must use int, not size_t.
int maxParallel=0;
if (!SafeConvert(parallel, maxParallel))
maxParallel = std::numeric_limits<int>::max();
#ifdef _OPENMP #ifdef _OPENMP
int threads = STDMIN(omp_get_max_threads(), int threads = STDMIN(omp_get_max_threads(), maxParallel);
static_cast<int>(STDMIN(static_cast<size_t>(parallel),
static_cast<size_t>(std::numeric_limits<int>::max()))));
#endif #endif
// http://stackoverflow.com/q/49604260/608639 // http://stackoverflow.com/q/49604260/608639
@ -260,7 +280,7 @@ size_t Scrypt::DeriveKey(byte*derived, size_t derivedLen, const byte*secret, siz
// 2: for i = 0 to p - 1 do // 2: for i = 0 to p - 1 do
#pragma omp for #pragma omp for
for (size_t i = 0; i < static_cast<size_t>(parallel); ++i) for (int i = 0; i < maxParallel; ++i)
{ {
// 3: B_i <-- MF(B_i, N) // 3: B_i <-- MF(B_i, N)
const ptrdiff_t offset = static_cast<ptrdiff_t>(blockSize*i*128); const ptrdiff_t offset = static_cast<ptrdiff_t>(blockSize*i*128);

View File

@ -76,7 +76,9 @@ public:
/// \details The parameter <tt>blockSize</tt> ("r" in the documents) specifies the block /// \details The parameter <tt>blockSize</tt> ("r" in the documents) specifies the block
/// size. /// size.
/// \details The <tt>parallelization</tt> parameter ("p" in the documents) is a positive /// \details The <tt>parallelization</tt> parameter ("p" in the documents) is a positive
/// integer less than or equal to <tt>((2^32-1) * 32) / (128 * r)</tt>. /// integer less than or equal to <tt>((2^32-1) * 32) / (128 * r)</tt>. Due to Microsoft
/// and its OpenMP 2.0 implementation <tt>parallelization</tt> is limited to
/// <tt>std::numeric_limits<int>::max()</tt>.
/// \details Scrypt always returns 1 because it only performs 1 iteration. Other /// \details Scrypt always returns 1 because it only performs 1 iteration. Other
/// derivation functions, like PBKDF's, will return more interesting values. /// derivation functions, like PBKDF's, will return more interesting values.
/// \details The Crypto++ implementation of Scrypt is limited by C++ datatypes. For /// \details The Crypto++ implementation of Scrypt is limited by C++ datatypes. For