From ca302c952e6393469651e01b7c3ae4686c7e0747 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Fri, 20 Jul 2018 13:24:04 -0400 Subject: [PATCH] Fix Solaris 11/Sparc crash in SHA-384 (GH #689, GH #403) I believe Andrew Marlow first reported it. At the time we could not get our hands on hardware to fully test things. Instead we were using -xmemalign=4i option as a band-aide to avoid running afoul of the Sparc instruction that moves 64-bits of data in one shot. --- GNUmakefile | 4 -- sha.cpp | 147 +++++++++++++++++++++++++++++--------------------- tweetnacl.cpp | 2 +- 3 files changed, 88 insertions(+), 65 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index ccc2d467..3bf9c5b4 100755 --- a/GNUmakefile +++ b/GNUmakefile @@ -566,10 +566,6 @@ CXXFLAGS += -KPIC endif # Add to all Solaris CXXFLAGS += -template=no%extdef -# http://github.com/weidai11/cryptopp/issues/403 -ifneq ($(IS_SPARC32)$(IS_SPARC64),00) -CXXFLAGS += -xmemalign=4i -endif SUN_CC10_BUGGY := $(shell $(CXX) -V 2>&1 | $(GREP) -c -E "CC: Sun .* 5\.10 .* (2009|2010/0[1-4])") ifneq ($(SUN_CC10_BUGGY),0) # -DCRYPTOPP_INCLUDE_VECTOR_CC is needed for Sun Studio 12u1 Sun C++ 5.10 SunOS_i386 128229-02 2009/09/21 and was fixed in May 2010 diff --git a/sha.cpp b/sha.cpp index ea0b02d3..69577f3d 100644 --- a/sha.cpp +++ b/sha.cpp @@ -161,18 +161,18 @@ ANONYMOUS_NAMESPACE_END std::string SHA1::AlgorithmProvider() const { #if CRYPTOPP_SHANI_AVAILABLE - if (HasSHA()) - return "SHANI"; + if (HasSHA()) + return "SHANI"; #endif #if CRYPTOPP_SSE2_ASM_AVAILABLE - if (HasSSE2()) - return "SSE2"; + if (HasSSE2()) + return "SSE2"; #endif #if CRYPTOPP_ARM_SHA1_AVAILABLE - if (HasSHA1()) - return "ARMv8"; + if (HasSHA1()) + return "ARMv8"; #endif - return "C++"; + return "C++"; } void SHA1::InitState(HashWordType *state) @@ -347,27 +347,27 @@ ANONYMOUS_NAMESPACE_END std::string SHA256_AlgorithmProvider() { #if CRYPTOPP_SHANI_AVAILABLE - if (HasSHA()) - return "SHANI"; + if (HasSHA()) + return "SHANI"; #endif #if CRYPTOPP_SSE2_ASM_AVAILABLE - if (HasSSE2()) - return "SSE2"; + if (HasSSE2()) + return "SSE2"; #endif #if CRYPTOPP_ARM_SHA2_AVAILABLE - if (HasSHA2()) - return "ARMv8"; + if (HasSHA2()) + return "ARMv8"; #endif #if (CRYPTOPP_POWER8_SHA_AVAILABLE) - if (HasSHA256()) - return "Power8"; + if (HasSHA256()) + return "Power8"; #endif - return "C++"; + return "C++"; } std::string SHA224::AlgorithmProvider() const { - return SHA256_AlgorithmProvider(); + return SHA256_AlgorithmProvider(); } void SHA224::InitState(HashWordType *state) @@ -718,7 +718,7 @@ void CRYPTOPP_FASTCALL SHA256_HashMultipleBlocks_SSE2(word32 *state, const word3 std::string SHA256::AlgorithmProvider() const { - return SHA256_AlgorithmProvider(); + return SHA256_AlgorithmProvider(); } void SHA256::Transform(word32 *state, const word32 *data) @@ -868,24 +868,24 @@ size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length) std::string SHA512_AlgorithmProvider() { #if CRYPTOPP_SSE2_ASM_AVAILABLE - if (HasSSE2()) - return "SSE2"; + if (HasSSE2()) + return "SSE2"; #endif #if (CRYPTOPP_POWER8_SHA_AVAILABLE) - if (HasSHA512()) - return "Power8"; + if (HasSHA512()) + return "Power8"; #endif - return "C++"; + return "C++"; } std::string SHA384::AlgorithmProvider() const { - return SHA512_AlgorithmProvider(); + return SHA512_AlgorithmProvider(); } std::string SHA512::AlgorithmProvider() const { - return SHA512_AlgorithmProvider(); + return SHA512_AlgorithmProvider(); } void SHA384::InitState(HashWordType *state) @@ -1166,7 +1166,7 @@ ANONYMOUS_NAMESPACE_BEGIN #define g(i) T[(6-i)&7] #define h(i) T[(7-i)&7] -#define blk0(i) (W[i]=data[i]) +#define blk0(i) (W[i]=D[i]) #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15])) #define Ch(x,y,z) (z^(x&(y^z))) @@ -1185,9 +1185,14 @@ void SHA512_HashBlock_CXX(word64 *state, const word64 *data) CRYPTOPP_ASSERT(state); CRYPTOPP_ASSERT(data); - word64 W[16]={0}, T[8]; + word64 W[16]={0}, D[16], T[8]; + /* Copy context->state[] to working vars */ - memcpy(T, state, sizeof(T)); + std::memcpy(T, state, sizeof(T)); + + /* Solaris/Sparc64 crash */ + std::memcpy(D, data, sizeof(D)); + /* 80 operations, partially loop unrolled */ for (unsigned int j=0; j<80; j+=16) { @@ -1196,40 +1201,39 @@ void SHA512_HashBlock_CXX(word64 *state, const word64 *data) R( 8); R( 9); R(10); R(11); R(12); R(13); R(14); R(15); } - /* Add the working vars back into context.state[] */ - state[0] += a(0); - state[1] += b(0); - state[2] += c(0); - state[3] += d(0); - state[4] += e(0); - state[5] += f(0); - state[6] += g(0); - state[7] += h(0); + + /* Solaris 11/Sparc64 crash */ + if (IsAligned(state) == true) + { + /* Add the working vars back into context.state[] */ + state[0] += a(0); + state[1] += b(0); + state[2] += c(0); + state[3] += d(0); + state[4] += e(0); + state[5] += f(0); + state[6] += g(0); + state[7] += h(0); + } + else + { + /* Reuse W[] */ + std::memcpy(W, state, 8 * sizeof(W[0])); + + /* Add the working vars back into context.state[] */ + W[0] += a(0); + W[1] += b(0); + W[2] += c(0); + W[3] += d(0); + W[4] += e(0); + W[5] += f(0); + W[6] += g(0); + W[7] += h(0); + + std::memcpy(state, W, 8 * sizeof(W[0])); + } } -#undef Ch -#undef Maj - -#undef s0 -#undef s1 -#undef S0 -#undef S1 - -#undef blk0 -#undef blk1 -#undef blk2 - -#undef R - -#undef a -#undef b -#undef c -#undef d -#undef e -#undef f -#undef g -#undef h - ANONYMOUS_NAMESPACE_END void SHA512::Transform(word64 *state, const word64 *data) @@ -1255,6 +1259,29 @@ void SHA512::Transform(word64 *state, const word64 *data) SHA512_HashBlock_CXX(state, data); } +#undef Ch +#undef Maj + +#undef s0 +#undef s1 +#undef S0 +#undef S1 + +#undef blk0 +#undef blk1 +#undef blk2 + +#undef R + +#undef a +#undef b +#undef c +#undef d +#undef e +#undef f +#undef g +#undef h + NAMESPACE_END #endif // Not CRYPTOPP_GENERATE_X64_MASM diff --git a/tweetnacl.cpp b/tweetnacl.cpp index 05e66179..aec6210e 100644 --- a/tweetnacl.cpp +++ b/tweetnacl.cpp @@ -759,7 +759,7 @@ int crypto_sign_sk2pk(byte *pk, const byte *sk) { byte d[64]; gf p[4]; - int i; + // int i; // randombytes(sk, 32); crypto_hash(d, sk, 32);