diff --git a/argnames.h b/argnames.h index b46d3924..a8315f21 100644 --- a/argnames.h +++ b/argnames.h @@ -81,6 +81,11 @@ CRYPTOPP_DEFINE_NAME_STRING(TableSize) //!< int, in bytes CRYPTOPP_DEFINE_NAME_STRING(Blinding) //!< bool, timing attack mitigations, ON by default CRYPTOPP_DEFINE_NAME_STRING(DerivedKey) //!< ByteArrayParameter, key derivation, derived key CRYPTOPP_DEFINE_NAME_STRING(DerivedKeyLength) //!< int, key derivation, derived key length in bytes +CRYPTOPP_DEFINE_NAME_STRING(Personalization) //!< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(PersonalizationSize) //!< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(Salt) //!< ConstByteArrayParameter +CRYPTOPP_DEFINE_NAME_STRING(SaltSize) //!< int, in bytes +CRYPTOPP_DEFINE_NAME_STRING(TreeMode) //< byte DOCUMENTED_NAMESPACE_END NAMESPACE_END diff --git a/blake2.cpp b/blake2.cpp index 93be4cd9..e72f8648 100644 --- a/blake2.cpp +++ b/blake2.cpp @@ -1,11 +1,13 @@ // blake2.cpp - written and placed in the public domain by Jeffrey Walton and Zooko // Wilcox-O'Hearn. Copyright assigned to the Crypto++ project. -// Based on Aumasson, Neves, Wilcox-O’Hearn and Winnerlein's reference BLAKE2 +// Based on Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's reference BLAKE2 // implementation at http://github.com/BLAKE2/BLAKE2. #include "pch.h" #include "config.h" #include "cryptlib.h" +#include "argnames.h" +#include "algparam.h" #include "blake2.h" #include "cpu.h" @@ -63,7 +65,8 @@ template<> struct CRYPTOPP_NO_VTABLE BLAKE2_IV { CRYPTOPP_CONSTANT(IVSIZE = 8); - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) static const word32 iv[8]; + // Always align for NEON and SSE + CRYPTOPP_ALIGN_DATA(16) static const word32 iv[8]; }; const word32 BLAKE2_IV::iv[8] = { @@ -77,7 +80,8 @@ template<> struct CRYPTOPP_NO_VTABLE BLAKE2_IV { CRYPTOPP_CONSTANT(IVSIZE = 8); - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) static const word64 iv[8]; + // Always align for NEON and SSE + CRYPTOPP_ALIGN_DATA(16) static const word64 iv[8]; }; const word64 BLAKE2_IV::iv[8] = { @@ -97,7 +101,8 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_Sigma {}; template<> struct CRYPTOPP_NO_VTABLE BLAKE2_Sigma { - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) static const byte sigma[10][16]; + // Always align for NEON and SSE + CRYPTOPP_ALIGN_DATA(16) static const byte sigma[10][16]; }; const byte BLAKE2_Sigma::sigma[10][16] = { @@ -117,7 +122,8 @@ const byte BLAKE2_Sigma::sigma[10][16] = { template<> struct CRYPTOPP_NO_VTABLE BLAKE2_Sigma { - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) static const byte sigma[12][16]; + // Always align for NEON and SSE + CRYPTOPP_ALIGN_DATA(16) static const byte sigma[12][16]; }; const byte BLAKE2_Sigma::sigma[12][16] = { @@ -233,23 +239,57 @@ BLAKE2_ParameterBlock::BLAKE2_ParameterBlock(size_t digestLen, size_t keyL } template -void BLAKE2_Base::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs&) +void BLAKE2_Base::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs& params) { if (key && length) { - AlignedSecByteBlock k(BLOCKSIZE); - memcpy_s(k, BLOCKSIZE, key, length); + AlignedSecByteBlock temp(BLOCKSIZE); + memcpy_s(temp, BLOCKSIZE, key, length); const size_t rem = BLOCKSIZE - length; if (rem) - memset(k+length, 0x00, rem); + memset(temp+length, 0x00, rem); - m_key.swap(k); + m_key.swap(temp); } else { m_key.resize(0); } + + // Zero everything except the two trailing strings + ParameterBlock& block = *m_block; + const size_t head = sizeof(block) - sizeof(block.personalization) - sizeof(block.salt); + memset(m_block.data(), 0x00, head); + + block.keyLength = (byte)length; + block.digestLength = (byte)params.GetIntValueWithDefault(Name::DigestSize(), DIGESTSIZE); + block.fanout = block.depth = 1; + + ConstByteArrayParameter t; + if (params.GetValue(Name::Salt(), t)) + { + memcpy_s(block.salt, sizeof(block.salt), t.begin(), t.size()); + const size_t rem = sizeof(block.salt) - t.size(); + if (rem) + memset(block.salt+rem, 0x00, rem); + } + else + { + memset(block.salt, 0x00, sizeof(block.salt)); + } + + if (params.GetValue(Name::Personalization(), t)) + { + memcpy_s(block.personalization, sizeof(block.personalization), t.begin(), t.size()); + const size_t rem = sizeof(block.personalization) - t.size(); + if (rem) + memset(block.personalization+rem, 0x00, rem); + } + else + { + memset(block.personalization, 0x00, sizeof(block.personalization)); + } } template @@ -271,13 +311,15 @@ BLAKE2_Base::BLAKE2_Base(bool treeMode, unsigned int digestSize) : m template BLAKE2_Base::BLAKE2_Base(const byte *key, size_t keyLength, const byte* salt, size_t saltLength, const byte* personalization, size_t personalizationLength, bool treeMode, unsigned int digestSize) - : m_block(ParameterBlock(digestSize, keyLength, salt, saltLength, - personalization, personalizationLength)), m_digestSize(digestSize), m_treeMode(treeMode) + : m_digestSize(digestSize), m_treeMode(treeMode) { this->ThrowIfInvalidKeyLength(keyLength); this->ThrowIfInvalidTruncatedSize(digestSize); + ThrowIfInvalidSalt(saltLength); + ThrowIfInvalidPersonalization(personalizationLength); - UncheckedSetKey(key, static_cast(keyLength), g_nullNameValuePairs); + UncheckedSetKey(key, static_cast(keyLength), MakeParameters(Name::DigestSize(),(int)digestSize)(Name::TreeMode(),treeMode, false) + (Name::Salt(), ConstByteArrayParameter(salt, saltLength))(Name::Personalization(), ConstByteArrayParameter(personalization, personalizationLength))); Restart(); } @@ -285,7 +327,7 @@ template void BLAKE2_Base::Restart() { static const W zero[2] = {0,0}; - Restart(m_block, zero); + Restart(*m_block, zero); } template @@ -293,22 +335,23 @@ void BLAKE2_Base::Restart(const BLAKE2_ParameterBlock& bloc { // We take a parameter block as a parameter to allow customized state. // Avoid the copy of the parameter block when we are passing our own block. - if (&block != &m_block) + if (&block != m_block.data()) { - m_block = block; - m_block.digestLength = (byte)m_digestSize; - m_block.keyLength = (byte)m_key.size(); + memcpy_s(m_block, sizeof(*m_block), &block, sizeof(block)); + (*m_block).digestLength = (byte)m_digestSize; + (*m_block).keyLength = (byte)m_key.size(); } - m_state.t[0] = m_state.t[1] = 0, m_state.f[0] = m_state.f[1] = 0, m_state.length = 0; + State& state = *m_state; + state.t[0] = state.t[1] = 0, state.f[0] = state.f[1] = 0, state.length = 0; if (counter != NULL) { - m_state.t[0] = counter[0]; - m_state.t[1] = counter[1]; + state.t[0] = counter[0]; + state.t[1] = counter[1]; } - PutBlock put(&m_block, m_state.h); + PutBlock put(m_block, state.h); put(BLAKE2_IV::iv[0])(BLAKE2_IV::iv[1])(BLAKE2_IV::iv[2])(BLAKE2_IV::iv[3]); put(BLAKE2_IV::iv[4])(BLAKE2_IV::iv[5])(BLAKE2_IV::iv[6])(BLAKE2_IV::iv[7]); @@ -321,63 +364,64 @@ void BLAKE2_Base::Restart(const BLAKE2_ParameterBlock& bloc template void BLAKE2_Base::Update(const byte *input, size_t length) { - if (m_state.length + length > BLOCKSIZE) + State& state = *m_state; + if (state.length + length > BLOCKSIZE) { // Complete current block - const size_t fill = BLOCKSIZE - m_state.length; - memcpy_s(&m_state.buffer[m_state.length], fill, input, fill); + const size_t fill = BLOCKSIZE - state.length; + memcpy_s(&state.buffer[state.length], fill, input, fill); IncrementCounter(); - Compress(m_state.buffer); - m_state.length = 0; + Compress(state.buffer); + state.length = 0; - length -= fill; - input += fill; + length -= fill, input += fill; // Compress in-place to avoid copies while (length > BLOCKSIZE) { IncrementCounter(); Compress(input); - length -= BLOCKSIZE; - input += BLOCKSIZE; + length -= BLOCKSIZE, input += BLOCKSIZE; } } if (input && length) { - memcpy_s(&m_state.buffer[m_state.length], BLOCKSIZE - m_state.length, input, length); - m_state.length += static_cast(length); + memcpy_s(&state.buffer[state.length], BLOCKSIZE - state.length, input, length); + state.length += static_cast(length); } } template void BLAKE2_Base::TruncatedFinal(byte *hash, size_t size) { + State& state = *m_state; + // Set last block unconditionally - m_state.f[0] = static_cast(-1); + state.f[0] = static_cast(-1); // Set last node if tree mode if (m_treeMode) - m_state.f[1] = static_cast(-1); + state.f[1] = static_cast(-1); // Increment counter for tail bytes only - IncrementCounter(m_state.length); + IncrementCounter(state.length); - memset(m_state.buffer + m_state.length, 0x00, BLOCKSIZE - m_state.length); - Compress(m_state.buffer); + memset(state.buffer + state.length, 0x00, BLOCKSIZE - state.length); + Compress(state.buffer); if (size >= DIGESTSIZE) { // Write directly to the caller buffer PutBlock put(NULL, hash); - put(m_state.h[0])(m_state.h[1])(m_state.h[2])(m_state.h[3])(m_state.h[4])(m_state.h[5])(m_state.h[6])(m_state.h[7]); + put(state.h[0])(state.h[1])(state.h[2])(state.h[3])(state.h[4])(state.h[5])(state.h[6])(state.h[7]); } else { FixedSizeAlignedSecBlock buffer; PutBlock put(NULL, buffer); - put(m_state.h[0])(m_state.h[1])(m_state.h[2])(m_state.h[3])(m_state.h[4])(m_state.h[5])(m_state.h[6])(m_state.h[7]); + put(state.h[0])(state.h[1])(state.h[2])(state.h[3])(state.h[4])(state.h[5])(state.h[6])(state.h[7]); memcpy_s(hash, DIGESTSIZE, buffer, size); } @@ -388,8 +432,9 @@ void BLAKE2_Base::TruncatedFinal(byte *hash, size_t size) template void BLAKE2_Base::IncrementCounter(size_t count) { - m_state.t[0] += static_cast(count); - m_state.t[1] += !!(m_state.t[0] < count); + State& state = *m_state; + state.t[0] += static_cast(count); + state.t[1] += !!(state.t[0] < count); } template <> @@ -397,7 +442,7 @@ void BLAKE2_Base::Compress(const byte *input) { // Selects the most advanced implmentation at runtime static const pfnCompress64 s_pfn = InitializeCompress64Fn(); - s_pfn(input, m_state); + s_pfn(input, *m_state); } template <> @@ -405,7 +450,7 @@ void BLAKE2_Base::Compress(const byte *input) { // Selects the most advanced implmentation at runtime static const pfnCompress32 s_pfn = InitializeCompress32Fn(); - s_pfn(input, m_state); + s_pfn(input, *m_state); } void BLAKE2_CXX_Compress64(const byte* input, BLAKE2_State& state) @@ -3387,8 +3432,8 @@ static void BLAKE2_NEON_Compress32(const byte* input, BLAKE2_State())); assert(IsAlignedOn(&state.t[0],GetAlignmentOf())); - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) uint32_t m0[4], m1[4], m2[4], m3[4], m4[4], m5[4], m6[4], m7[4]; - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) uint32_t m8[4], m9[4], m10[4], m11[4], m12[4], m13[4], m14[4], m15[4]; + CRYPTOPP_ALIGN_DATA(16) uint32_t m0[4], m1[4], m2[4], m3[4], m4[4], m5[4], m6[4], m7[4]; + CRYPTOPP_ALIGN_DATA(16) uint32_t m8[4], m9[4], m10[4], m11[4], m12[4], m13[4], m14[4], m15[4]; GetBlock get(input); get(m0[0])(m1[0])(m2[0])(m3[0])(m4[0])(m5[0])(m6[0])(m7[0])(m8[0])(m9[0])(m10[0])(m11[0])(m12[0])(m13[0])(m14[0])(m15[0]); diff --git a/blake2.h b/blake2.h index 23030e2a..1f70aa70 100644 --- a/blake2.h +++ b/blake2.h @@ -1,6 +1,6 @@ // blake2.h - written and placed in the public domain by Jeffrey Walton and Zooko // Wilcox-O'Hearn. Copyright assigned to the Crypto++ project. -// Based on Aumasson, Neves, Wilcox-O’Hearn and Winnerlein's reference BLAKE2 +// Based on Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's reference BLAKE2 // implementation at http://github.com/BLAKE2/BLAKE2. //! \file blake2.h @@ -23,17 +23,6 @@ NAMESPACE_BEGIN(CryptoPP) -// Can't use GetAlignmentOf() because its not a constant expression. GCC has -// some bugs spanning 4.0 through 4.9, so we can't use a template parameter with -// CRYPTOPP_CONSTANT, either. Also see http://stackoverflow.com/q/36642315. -#if (CRYPTOPP_BOOL_ALIGN16 || CRYPTOPP_BOOL_NEON_INTRINSICS_AVAILABLE) -# define BLAKE2_DALIGN 16 -#elif defined(_M_X64) || defined(__LP64__) || defined(__x86_64__) || defined(__amd64__) || defined(__aarch64__) -# define BLAKE2_DALIGN 8 -#else -# define BLAKE2_DALIGN 4 -#endif - //! \class BLAKE2_Info //! \brief BLAKE2 hash information //! \tparam T_64bit flag indicating 64-bit @@ -49,7 +38,6 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_Info : public VariableKeyLength<(T_64bit ? 64 : CRYPTOPP_CONSTANT(DIGESTSIZE = (T_64bit ? 64 : 32)) CRYPTOPP_CONSTANT(SALTSIZE = (T_64bit ? 16 : 8)) CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = (T_64bit ? 16 : 8)) - CRYPTOPP_CONSTANT(ALIGNSIZE = BLAKE2_DALIGN); static const char *StaticAlgorithmName() {return (T_64bit ? "BLAKE2b" : "BLAKE2s");} }; @@ -72,12 +60,6 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info::DIGESTSIZE); CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info::PERSONALIZATIONSIZE); - ~BLAKE2_ParameterBlock() - { - // Easier than SecBlock or using an AlignedAllocatorWithCleanup - SecureWipeBuffer(reinterpret_cast(this), sizeof(*this)); - }; - BLAKE2_ParameterBlock() { memset(this, 0x00, sizeof(*this)); @@ -96,7 +78,6 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength, const byte* personalization, size_t personalizationLength); - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) byte digestLength; byte keyLength, fanout, depth; byte leafLength[4]; @@ -114,12 +95,6 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info::DIGESTSIZE); CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info::PERSONALIZATIONSIZE); - ~BLAKE2_ParameterBlock() - { - // Easier than SecBlock or using an AlignedAllocatorWithCleanup - SecureWipeBuffer(reinterpret_cast(this), sizeof(*this)); - }; - BLAKE2_ParameterBlock() { memset(this, 0x00, sizeof(*this)); @@ -138,7 +113,6 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength, const byte* personalization, size_t personalizationLength); - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) byte digestLength; byte keyLength, fanout, depth; byte leafLength[4]; @@ -157,15 +131,8 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock template struct CRYPTOPP_NO_VTABLE BLAKE2_State { - // CRYPTOPP_CONSTANT(ALIGNSIZE = BLAKE2_Info::ALIGNSIZE); CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info::BLOCKSIZE); - ~BLAKE2_State() - { - // Easier than SecBlock or using an AlignedAllocatorWithCleanup - SecureWipeBuffer(reinterpret_cast(this), sizeof(*this)); - }; - BLAKE2_State() { // Set all members except scratch buffer[] @@ -175,11 +142,9 @@ struct CRYPTOPP_NO_VTABLE BLAKE2_State } // SSE2, SSE4 and NEON depend upon t[] and f[] being side-by-side - CRYPTOPP_ALIGN_DATA(BLAKE2_DALIGN) - W h[8]; - W t[2], f[2]; - byte buffer[BLOCKSIZE]; + W h[8], t[2], f[2]; size_t length; + byte buffer[BLOCKSIZE]; }; //! \class BLAKE2_Base @@ -198,7 +163,6 @@ public: CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info::DIGESTSIZE); CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info::BLOCKSIZE); - CRYPTOPP_CONSTANT(ALIGNSIZE = BLAKE2_Info::ALIGNSIZE); typedef BLAKE2_ParameterBlock ParameterBlock; typedef BLAKE2_State State; @@ -217,7 +181,7 @@ public: std::string AlgorithmName() const {return std::string(StaticAlgorithmName()) + "-" + IntToString(this->DigestSize()*8);} unsigned int DigestSize() const {return m_digestSize;} - unsigned int OptimalDataAlignment() const {return ALIGNSIZE;} + unsigned int OptimalDataAlignment() const {return (CRYPTOPP_BOOL_ALIGN16 ? 16 : GetAlignmentOf());} void Update(const byte *input, size_t length); void Restart(); @@ -257,8 +221,8 @@ protected: void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params); private: - State m_state; - ParameterBlock m_block; + FixedSizeAlignedSecBlock m_state; + FixedSizeAlignedSecBlock m_block; AlignedSecByteBlock m_key; word32 m_digestSize; bool m_treeMode;