Rewrite BLAKE2 classes to remove intermediate base class

This commit is contained in:
Jeffrey Walton 2018-11-03 10:33:35 -04:00
parent 06867e5caf
commit 600e2a8be4
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
4 changed files with 521 additions and 379 deletions

View File

@ -27,6 +27,28 @@
# undef CRYPTOPP_POWER8_AVAILABLE
#endif
NAMESPACE_BEGIN(CryptoPP)
// Export the tables to the SIMD files
extern const word32 BLAKE2S_IV[8];
extern const word64 BLAKE2B_IV[8];
CRYPTOPP_ALIGN_DATA(16)
const word32 BLAKE2S_IV[8] = {
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
CRYPTOPP_ALIGN_DATA(16)
const word64 BLAKE2B_IV[8] = {
W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)
};
NAMESPACE_END
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::byte;
@ -34,27 +56,6 @@ using CryptoPP::word32;
using CryptoPP::word64;
using CryptoPP::rotrConstant;
template <class W, bool T_64bit>
struct BLAKE2_IV
{
CRYPTOPP_ALIGN_DATA(16)
static const W iv[8];
};
template <>
const word32 BLAKE2_IV<word32, false>::iv[8] = {
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
template <>
const word64 BLAKE2_IV<word64, true>::iv[8] = {
W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)
};
CRYPTOPP_ALIGN_DATA(16)
const byte BLAKE2S_SIGMA[10][16] = {
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
@ -141,28 +142,28 @@ ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
void BLAKE2_Compress32_CXX(const byte* input, BLAKE2_State<word32, false>& state);
void BLAKE2_Compress64_CXX(const byte* input, BLAKE2_State<word64, true>& state);
void BLAKE2_Compress32_CXX(const byte* input, BLAKE2s_State& state);
void BLAKE2_Compress64_CXX(const byte* input, BLAKE2b_State& state);
#if CRYPTOPP_SSE41_AVAILABLE
extern void BLAKE2_Compress32_SSE4(const byte* input, BLAKE2_State<word32, false>& state);
extern void BLAKE2_Compress64_SSE4(const byte* input, BLAKE2_State<word64, true>& state);
extern void BLAKE2_Compress32_SSE4(const byte* input, BLAKE2s_State& state);
extern void BLAKE2_Compress64_SSE4(const byte* input, BLAKE2b_State& state);
#endif
#if CRYPTOPP_ARM_NEON_AVAILABLE
extern void BLAKE2_Compress32_NEON(const byte* input, BLAKE2_State<word32, false>& state);
extern void BLAKE2_Compress64_NEON(const byte* input, BLAKE2_State<word64, true>& state);
extern void BLAKE2_Compress32_NEON(const byte* input, BLAKE2s_State& state);
extern void BLAKE2_Compress64_NEON(const byte* input, BLAKE2b_State& state);
#endif
#if CRYPTOPP_POWER7_AVAILABLE
extern void BLAKE2_Compress32_POWER7(const byte* input, BLAKE2_State<word32, false>& state);
extern void BLAKE2_Compress32_POWER7(const byte* input, BLAKE2s_State& state);
#endif
#if CRYPTOPP_POWER8_AVAILABLE
extern void BLAKE2_Compress64_POWER8(const byte* input, BLAKE2_State<word64, true>& state);
extern void BLAKE2_Compress64_POWER8(const byte* input, BLAKE2b_State& state);
#endif
BLAKE2_ParameterBlock<false>::BLAKE2_ParameterBlock(size_t digestLen, size_t keyLen,
BLAKE2s_ParameterBlock::BLAKE2s_ParameterBlock(size_t digestLen, size_t keyLen,
const byte* saltStr, size_t saltLen,
const byte* personalizationStr, size_t personalizationLen)
{
@ -201,7 +202,7 @@ BLAKE2_ParameterBlock<false>::BLAKE2_ParameterBlock(size_t digestLen, size_t key
}
}
BLAKE2_ParameterBlock<true>::BLAKE2_ParameterBlock(size_t digestLen, size_t keyLen,
BLAKE2b_ParameterBlock::BLAKE2b_ParameterBlock(size_t digestLen, size_t keyLen,
const byte* saltStr, size_t saltLen,
const byte* personalizationStr, size_t personalizationLen)
{
@ -241,8 +242,7 @@ BLAKE2_ParameterBlock<true>::BLAKE2_ParameterBlock(size_t digestLen, size_t keyL
}
}
template<> // This specialization lacks rfu[] field
void BLAKE2_Base<word32, false>::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs& params)
void BLAKE2s::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs& params)
{
if (key && length)
{
@ -297,8 +297,7 @@ void BLAKE2_Base<word32, false>::UncheckedSetKey(const byte *key, unsigned int l
}
}
template<> // This specialization has rfu[] field
void BLAKE2_Base<word64, true>::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs& params)
void BLAKE2b::UncheckedSetKey(const byte *key, unsigned int length, const CryptoPP::NameValuePairs& params)
{
if (key && length)
{
@ -354,8 +353,24 @@ void BLAKE2_Base<word64, true>::UncheckedSetKey(const byte *key, unsigned int le
}
}
template <class W, bool T_64bit>
std::string BLAKE2_Base<W, T_64bit>::AlgorithmProvider() const
std::string BLAKE2b::AlgorithmProvider() const
{
#if defined(CRYPTOPP_SSE41_AVAILABLE)
if (HasSSE41())
return "SSE4.1";
#endif
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
return "NEON";
#endif
#if (CRYPTOPP_POWER8_AVAILABLE)
if (HasPower8())
return "Power8";
#endif
return "C++";
}
std::string BLAKE2s::AlgorithmProvider() const
{
#if defined(CRYPTOPP_SSE41_AVAILABLE)
if (HasSSE41())
@ -366,25 +381,13 @@ std::string BLAKE2_Base<W, T_64bit>::AlgorithmProvider() const
return "NEON";
#endif
#if (CRYPTOPP_POWER7_AVAILABLE)
if (HasPower7() && T_64bit == false)
if (HasPower7())
return "Power7";
#endif
#if (CRYPTOPP_POWER8_AVAILABLE)
if (HasPower8() && T_64bit == true)
return "Power8";
#endif
return "C++";
}
template <class W, bool T_64bit>
BLAKE2_Base<W, T_64bit>::BLAKE2_Base() : m_state(1), m_block(1), m_digestSize(DIGESTSIZE), m_treeMode(false)
{
UncheckedSetKey(NULLPTR, 0, g_nullNameValuePairs);
Restart();
}
template <class W, bool T_64bit>
BLAKE2_Base<W, T_64bit>::BLAKE2_Base(bool treeMode, unsigned int digestSize) : m_state(1), m_block(1), m_digestSize(digestSize), m_treeMode(treeMode)
BLAKE2s::BLAKE2s(bool treeMode, unsigned int digestSize) : m_state(1), m_block(1), m_digestSize(digestSize), m_treeMode(treeMode)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
@ -392,8 +395,15 @@ BLAKE2_Base<W, T_64bit>::BLAKE2_Base(bool treeMode, unsigned int digestSize) : m
Restart();
}
template <class W, bool T_64bit>
BLAKE2_Base<W, T_64bit>::BLAKE2_Base(const byte *key, size_t keyLength, const byte* salt, size_t saltLength,
BLAKE2b::BLAKE2b(bool treeMode, unsigned int digestSize) : m_state(1), m_block(1), m_digestSize(digestSize), m_treeMode(treeMode)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
UncheckedSetKey(NULLPTR, 0, MakeParameters(Name::DigestSize(), (int)digestSize)(Name::TreeMode(), treeMode, false));
Restart();
}
BLAKE2s::BLAKE2s(const byte *key, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength, bool treeMode, unsigned int digestSize)
: m_state(1), m_block(1), m_digestSize(digestSize), m_treeMode(treeMode)
{
@ -407,15 +417,33 @@ BLAKE2_Base<W, T_64bit>::BLAKE2_Base(const byte *key, size_t keyLength, const by
Restart();
}
template <class W, bool T_64bit>
void BLAKE2_Base<W, T_64bit>::Restart()
BLAKE2b::BLAKE2b(const byte *key, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength, bool treeMode, unsigned int digestSize)
: m_state(1), m_block(1), m_digestSize(digestSize), m_treeMode(treeMode)
{
static const W zero[2] = {0,0};
CRYPTOPP_ASSERT(keyLength <= MAX_KEYLENGTH);
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
CRYPTOPP_ASSERT(saltLength <= SALTSIZE);
CRYPTOPP_ASSERT(personalizationLength <= PERSONALIZATIONSIZE);
UncheckedSetKey(key, static_cast<unsigned int>(keyLength), MakeParameters(Name::DigestSize(),(int)digestSize)(Name::TreeMode(),treeMode, false)
(Name::Salt(), ConstByteArrayParameter(salt, saltLength))(Name::Personalization(), ConstByteArrayParameter(personalization, personalizationLength)));
Restart();
}
void BLAKE2s::Restart()
{
static const word32 zero[2] = {0,0};
Restart(*m_block.data(), zero);
}
template <class W, bool T_64bit>
void BLAKE2_Base<W, T_64bit>::Restart(const BLAKE2_ParameterBlock<T_64bit>& block, const W counter[2])
void BLAKE2b::Restart()
{
static const word64 zero[2] = {0,0};
Restart(*m_block.data(), zero);
}
void BLAKE2s::Restart(const BLAKE2s_ParameterBlock& block, const word32 counter[2])
{
// 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.
@ -435,8 +463,8 @@ void BLAKE2_Base<W, T_64bit>::Restart(const BLAKE2_ParameterBlock<T_64bit>& bloc
state.t[1] = counter[1];
}
const W* iv = BLAKE2_IV<W, T_64bit>::iv;
PutBlock<W, LittleEndian, true> put(m_block.data(), &state.h[0]);
const word32* iv = BLAKE2S_IV;
PutBlock<word32, LittleEndian, true> put(m_block.data(), &state.h[0]);
put(iv[0])(iv[1])(iv[2])(iv[3])(iv[4])(iv[5])(iv[6])(iv[7]);
// When BLAKE2 is keyed, the input stream is simply {key||message}. Key it
@ -445,8 +473,38 @@ void BLAKE2_Base<W, T_64bit>::Restart(const BLAKE2_ParameterBlock<T_64bit>& bloc
Update(m_key, m_key.size());
}
template <class W, bool T_64bit>
void BLAKE2_Base<W, T_64bit>::Update(const byte *input, size_t length)
void BLAKE2b::Restart(const BLAKE2b_ParameterBlock& block, const word64 counter[2])
{
// 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.data())
{
memcpy_s(m_block.data(), sizeof(ParameterBlock), &block, sizeof(ParameterBlock));
m_block.data()->digestLength = (byte)m_digestSize;
m_block.data()->keyLength = (byte)m_key.size();
}
State& state = *m_state.data();
state.t[0] = state.t[1] = 0, state.f[0] = state.f[1] = 0, state.length = 0;
if (counter != NULLPTR)
{
state.t[0] = counter[0];
state.t[1] = counter[1];
}
const word64* iv = BLAKE2B_IV;
PutBlock<word64, LittleEndian, true> put(m_block.data(), &state.h[0]);
put(iv[0])(iv[1])(iv[2])(iv[3])(iv[4])(iv[5])(iv[6])(iv[7]);
// When BLAKE2 is keyed, the input stream is simply {key||message}. Key it
// during Restart to avoid FirstPut and friends. Key size == 0 means no key.
if (m_key.size())
Update(m_key, m_key.size());
}
void BLAKE2s::Update(const byte *input, size_t length)
{
CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0));
if (length == 0) { return; }
@ -482,19 +540,55 @@ void BLAKE2_Base<W, T_64bit>::Update(const byte *input, size_t length)
}
}
template <class W, bool T_64bit>
void BLAKE2_Base<W, T_64bit>::TruncatedFinal(byte *hash, size_t size)
void BLAKE2b::Update(const byte *input, size_t length)
{
CRYPTOPP_ASSERT(!(input == NULLPTR && length != 0));
if (length == 0) { return; }
State& state = *m_state.data();
if (state.length + length > BLOCKSIZE)
{
// Complete current block
const size_t fill = BLOCKSIZE - state.length;
memcpy_s(&state.buffer[state.length], fill, input, fill);
IncrementCounter();
Compress(state.buffer);
state.length = 0;
length -= fill, input += fill;
// Compress in-place to avoid copies
while (length > BLOCKSIZE)
{
IncrementCounter();
Compress(input);
length -= BLOCKSIZE, input += BLOCKSIZE;
}
}
// Copy tail bytes
if (input && length)
{
CRYPTOPP_ASSERT(length <= BLOCKSIZE - state.length);
memcpy_s(&state.buffer[state.length], length, input, length);
state.length += static_cast<unsigned int>(length);
}
}
void BLAKE2s::TruncatedFinal(byte *hash, size_t size)
{
CRYPTOPP_ASSERT(hash != NULLPTR);
this->ThrowIfInvalidTruncatedSize(size);
// Set last block unconditionally
State& state = *m_state.data();
state.f[0] = ~static_cast<W>(0);
state.f[0] = ~static_cast<word32>(0);
// Set last node if tree mode
if (m_treeMode)
state.f[1] = ~static_cast<W>(0);
state.f[1] = ~static_cast<word32>(0);
// Increment counter for tail bytes only
IncrementCounter(state.length);
@ -508,40 +602,46 @@ void BLAKE2_Base<W, T_64bit>::TruncatedFinal(byte *hash, size_t size)
Restart();
}
template <class W, bool T_64bit>
void BLAKE2_Base<W, T_64bit>::IncrementCounter(size_t count)
void BLAKE2b::TruncatedFinal(byte *hash, size_t size)
{
CRYPTOPP_ASSERT(hash != NULLPTR);
this->ThrowIfInvalidTruncatedSize(size);
// Set last block unconditionally
State& state = *m_state.data();
state.f[0] = ~static_cast<word64>(0);
// Set last node if tree mode
if (m_treeMode)
state.f[1] = ~static_cast<word64>(0);
// Increment counter for tail bytes only
IncrementCounter(state.length);
std::memset(state.buffer + state.length, 0x00, BLOCKSIZE - state.length);
Compress(state.buffer);
// Copy to caller buffer
memcpy_s(hash, size, &state.h[0], size);
Restart();
}
void BLAKE2s::IncrementCounter(size_t count)
{
State& state = *m_state.data();
state.t[0] += static_cast<W>(count);
state.t[0] += static_cast<word32>(count);
state.t[1] += !!(state.t[0] < count);
}
template <>
void BLAKE2_Base<word64, true>::Compress(const byte *input)
void BLAKE2b::IncrementCounter(size_t count)
{
#if CRYPTOPP_SSE41_AVAILABLE
if(HasSSE41())
{
return BLAKE2_Compress64_SSE4(input, *m_state.data());
}
#endif
#if CRYPTOPP_ARM_NEON_AVAILABLE
if(HasNEON())
{
return BLAKE2_Compress64_NEON(input, *m_state.data());
}
#endif
#if CRYPTOPP_POWER8_AVAILABLE
if(HasPower8())
{
return BLAKE2_Compress64_POWER8(input, *m_state.data());
}
#endif
return BLAKE2_Compress64_CXX(input, *m_state.data());
State& state = *m_state.data();
state.t[0] += static_cast<word64>(count);
state.t[1] += !!(state.t[0] < count);
}
template <>
void BLAKE2_Base<word32, false>::Compress(const byte *input)
void BLAKE2s::Compress(const byte *input)
{
#if CRYPTOPP_SSE41_AVAILABLE
if(HasSSE41())
@ -564,7 +664,30 @@ void BLAKE2_Base<word32, false>::Compress(const byte *input)
return BLAKE2_Compress32_CXX(input, *m_state.data());
}
void BLAKE2_Compress64_CXX(const byte* input, BLAKE2_State<word64, true>& state)
void BLAKE2b::Compress(const byte *input)
{
#if CRYPTOPP_SSE41_AVAILABLE
if(HasSSE41())
{
return BLAKE2_Compress64_SSE4(input, *m_state.data());
}
#endif
#if CRYPTOPP_ARM_NEON_AVAILABLE
if(HasNEON())
{
return BLAKE2_Compress64_NEON(input, *m_state.data());
}
#endif
#if CRYPTOPP_POWER8_AVAILABLE
if(HasPower8())
{
return BLAKE2_Compress64_POWER8(input, *m_state.data());
}
#endif
return BLAKE2_Compress64_CXX(input, *m_state.data());
}
void BLAKE2_Compress64_CXX(const byte* input, BLAKE2b_State& state)
{
word64 m[16], v[16];
@ -574,7 +697,7 @@ void BLAKE2_Compress64_CXX(const byte* input, BLAKE2_State<word64, true>& state)
GetBlock<word64, LittleEndian, true> get2(&state.h[0]);
get2(v[0])(v[1])(v[2])(v[3])(v[4])(v[5])(v[6])(v[7]);
const word64* iv = BLAKE2_IV<word64, true>::iv;
const word64* iv = BLAKE2B_IV;
v[ 8] = iv[0];
v[ 9] = iv[1];
v[10] = iv[2];
@ -601,7 +724,7 @@ void BLAKE2_Compress64_CXX(const byte* input, BLAKE2_State<word64, true>& state)
state.h[i] = state.h[i] ^ ConditionalByteReverse(LittleEndian::ToEnum(), v[i] ^ v[i + 8]);
}
void BLAKE2_Compress32_CXX(const byte* input, BLAKE2_State<word32, false>& state)
void BLAKE2_Compress32_CXX(const byte* input, BLAKE2s_State& state)
{
word32 m[16], v[16];
@ -611,7 +734,7 @@ void BLAKE2_Compress32_CXX(const byte* input, BLAKE2_State<word32, false>& state
GetBlock<word32, LittleEndian, true> get2(&state.h[0]);
get2(v[0])(v[1])(v[2])(v[3])(v[4])(v[5])(v[6])(v[7]);
const word32* iv = BLAKE2_IV<word32, false>::iv;
const word32* iv = BLAKE2S_IV;
v[ 8] = iv[0];
v[ 9] = iv[1];
v[10] = iv[2];
@ -636,7 +759,4 @@ void BLAKE2_Compress32_CXX(const byte* input, BLAKE2_State<word32, false>& state
state.h[i] = state.h[i] ^ ConditionalByteReverse(LittleEndian::ToEnum(), v[i] ^ v[i + 8]);
}
template class BLAKE2_Base<word32, false>;
template class BLAKE2_Base<word64, true>;
NAMESPACE_END

522
blake2.h
View File

@ -24,251 +24,142 @@
NAMESPACE_BEGIN(CryptoPP)
/// \brief BLAKE2 hash information
/// \tparam T_64bit flag indicating 64-bit
/// \brief BLAKE2s hash information
/// \since Crypto++ 5.6.4
template <bool T_64bit>
struct BLAKE2_Info : public VariableKeyLength<(T_64bit ? 64 : 32),0,(T_64bit ? 64 : 32),1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
struct BLAKE2s_Info : public VariableKeyLength<32,0,32,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
{
typedef VariableKeyLength<(T_64bit ? 64 : 32),0,(T_64bit ? 64 : 32),1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH)
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH)
typedef VariableKeyLength<32,0,32,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH)
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH)
CRYPTOPP_CONSTANT(BLOCKSIZE = (T_64bit ? 128 : 64))
CRYPTOPP_CONSTANT(DIGESTSIZE = (T_64bit ? 64 : 32))
CRYPTOPP_CONSTANT(SALTSIZE = (T_64bit ? 16 : 8))
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = (T_64bit ? 16 : 8))
CRYPTOPP_CONSTANT(BLOCKSIZE = 64)
CRYPTOPP_CONSTANT(DIGESTSIZE = 32)
CRYPTOPP_CONSTANT(SALTSIZE = 8)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = 8)
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return (T_64bit ? "BLAKE2b" : "BLAKE2s");}
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2s";}
};
/// \brief BLAKE2 parameter block
/// \tparam T_64bit flag indicating 64-bit
/// \details BLAKE2b uses BLAKE2_ParameterBlock<true>, while BLAKE2s
/// uses BLAKE2_ParameterBlock<false>.
/// \brief BLAKE2b hash information
/// \since Crypto++ 5.6.4
template <bool T_64bit>
struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock
struct BLAKE2b_Info : public VariableKeyLength<64,0,64,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE>
{
typedef VariableKeyLength<64,0,64,1,SimpleKeyingInterface::NOT_RESYNCHRONIZABLE> KeyBase;
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = KeyBase::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = KeyBase::MAX_KEYLENGTH)
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = KeyBase::DEFAULT_KEYLENGTH)
CRYPTOPP_CONSTANT(BLOCKSIZE = 128)
CRYPTOPP_CONSTANT(DIGESTSIZE = 64)
CRYPTOPP_CONSTANT(SALTSIZE = 16)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = 16)
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2b";}
};
/// \brief BLAKE2b parameter block specialization
template<>
struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock<true>
/// \brief BLAKE2s parameter block
struct CRYPTOPP_NO_VTABLE BLAKE2s_ParameterBlock
{
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<true>::SALTSIZE)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<true>::DIGESTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<true>::PERSONALIZATIONSIZE)
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2s_Info::SALTSIZE)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2s_Info::DIGESTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2s_Info::PERSONALIZATIONSIZE)
BLAKE2_ParameterBlock()
{
memset(this, 0x00, sizeof(*this));
digestLength = DIGESTSIZE;
fanout = depth = 1;
}
BLAKE2s_ParameterBlock()
{
memset(this, 0x00, sizeof(*this));
digestLength = DIGESTSIZE;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
memset(this, 0x00, sizeof(*this));
digestLength = (byte)digestSize;
fanout = depth = 1;
}
BLAKE2s_ParameterBlock(size_t digestSize)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
memset(this, 0x00, sizeof(*this));
digestLength = (byte)digestSize;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength);
BLAKE2s_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength);
byte digestLength;
byte keyLength, fanout, depth;
byte leafLength[4];
byte nodeOffset[8];
byte nodeDepth, innerLength, rfu[14];
byte salt[SALTSIZE];
byte personalization[PERSONALIZATIONSIZE];
byte digestLength;
byte keyLength, fanout, depth;
byte leafLength[4];
byte nodeOffset[6];
byte nodeDepth, innerLength;
byte salt[SALTSIZE];
byte personalization[PERSONALIZATIONSIZE];
};
/// \brief BLAKE2s parameter block specialization
template<>
struct CRYPTOPP_NO_VTABLE BLAKE2_ParameterBlock<false>
/// \brief BLAKE2b parameter block
struct CRYPTOPP_NO_VTABLE BLAKE2b_ParameterBlock
{
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<false>::SALTSIZE)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<false>::DIGESTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<false>::PERSONALIZATIONSIZE)
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2b_Info::SALTSIZE)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2b_Info::DIGESTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2b_Info::PERSONALIZATIONSIZE)
BLAKE2_ParameterBlock()
{
memset(this, 0x00, sizeof(*this));
digestLength = DIGESTSIZE;
fanout = depth = 1;
}
BLAKE2b_ParameterBlock()
{
memset(this, 0x00, sizeof(*this));
digestLength = DIGESTSIZE;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
memset(this, 0x00, sizeof(*this));
digestLength = (byte)digestSize;
fanout = depth = 1;
}
BLAKE2b_ParameterBlock(size_t digestSize)
{
CRYPTOPP_ASSERT(digestSize <= DIGESTSIZE);
memset(this, 0x00, sizeof(*this));
digestLength = (byte)digestSize;
fanout = depth = 1;
}
BLAKE2_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength);
BLAKE2b_ParameterBlock(size_t digestSize, size_t keyLength, const byte* salt, size_t saltLength,
const byte* personalization, size_t personalizationLength);
byte digestLength;
byte keyLength, fanout, depth;
byte leafLength[4];
byte nodeOffset[6];
byte nodeDepth, innerLength;
byte salt[SALTSIZE];
byte personalization[PERSONALIZATIONSIZE];
byte digestLength;
byte keyLength, fanout, depth;
byte leafLength[4];
byte nodeOffset[8];
byte nodeDepth, innerLength, rfu[14];
byte salt[SALTSIZE];
byte personalization[PERSONALIZATIONSIZE];
};
/// \brief BLAKE2 state information
/// \tparam W word type
/// \tparam T_64bit flag indicating 64-bit
/// \details BLAKE2b uses BLAKE2_State<word64, true>, while BLAKE2s
/// uses BLAKE2_State<word32, false>.
/// \brief BLAKE2s state information
/// \since Crypto++ 5.6.4
template <class W, bool T_64bit>
struct CRYPTOPP_NO_VTABLE BLAKE2_State
struct CRYPTOPP_NO_VTABLE BLAKE2s_State
{
CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info<T_64bit>::BLOCKSIZE)
BLAKE2s_State()
{
// Set all members except scratch buffer[]
h[0]=h[1]=h[2]=h[3]=h[4]=h[5]=h[6]=h[7] = 0;
t[0]=t[1]=f[0]=f[1] = 0;
length = 0;
}
BLAKE2_State()
{
// Set all members except scratch buffer[]
h[0]=h[1]=h[2]=h[3]=h[4]=h[5]=h[6]=h[7] = 0;
t[0]=t[1]=f[0]=f[1] = 0;
length = 0;
}
// SSE2, SSE4 and NEON depend upon t[] and f[] being side-by-side
W h[8], t[2], f[2];
byte buffer[BLOCKSIZE];
size_t length;
// SSE2, SSE4 and NEON depend upon t[] and f[] being side-by-side
word32 h[8], t[2], f[2];
byte buffer[BLAKE2s_Info::BLOCKSIZE];
size_t length;
};
/// \brief BLAKE2 hash implementation
/// \tparam W word type
/// \tparam T_64bit flag indicating 64-bit
/// \details BLAKE2b uses BLAKE2_Base<word64, true>, while BLAKE2s
/// uses BLAKE2_Base<word32, false>.
/// \brief BLAKE2b state information
/// \since Crypto++ 5.6.4
template <class W, bool T_64bit>
class BLAKE2_Base : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2_Info<T_64bit> >
struct CRYPTOPP_NO_VTABLE BLAKE2b_State
{
public:
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2_Info<T_64bit>::DEFAULT_KEYLENGTH)
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2_Info<T_64bit>::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2_Info<T_64bit>::MAX_KEYLENGTH)
BLAKE2b_State()
{
// Set all members except scratch buffer[]
h[0]=h[1]=h[2]=h[3]=h[4]=h[5]=h[6]=h[7] = 0;
t[0]=t[1]=f[0]=f[1] = 0;
length = 0;
}
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2_Info<T_64bit>::DIGESTSIZE)
CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2_Info<T_64bit>::BLOCKSIZE)
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2_Info<T_64bit>::SALTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2_Info<T_64bit>::PERSONALIZATIONSIZE)
typedef BLAKE2_State<W, T_64bit> State;
typedef BLAKE2_ParameterBlock<T_64bit> ParameterBlock;
typedef SecBlock<State, AllocatorWithCleanup<State, true> > AlignedState;
typedef SecBlock<ParameterBlock, AllocatorWithCleanup<ParameterBlock, true> > AlignedParameterBlock;
virtual ~BLAKE2_Base() {}
/// \brief Retrieve the static algorithm name
/// \returns the algorithm name (BLAKE2s or BLAKE2b)
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return BLAKE2_Info<T_64bit>::StaticAlgorithmName();}
/// \brief Retrieve the object's name
/// \returns the object's algorithm name following RFC 7693
/// \details Object algorithm name follows the naming described in
/// <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
/// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
std::string AlgorithmName() const {return std::string(StaticAlgorithmName()) + "-" + IntToString(this->DigestSize()*8);}
unsigned int DigestSize() const {return m_digestSize;}
unsigned int OptimalDataAlignment() const {return (CRYPTOPP_BOOL_ALIGN16 ? 16 : GetAlignmentOf<W>());}
void Update(const byte *input, size_t length);
void Restart();
/// \brief Restart a hash with parameter block and counter
/// \param block parameter block
/// \param counter counter array
/// \details Parameter block is persisted across calls to Restart().
void Restart(const BLAKE2_ParameterBlock<T_64bit>& block, const W counter[2]);
/// \brief Set tree mode
/// \param mode the new tree mode
/// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
/// If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
/// <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
/// Tree mode is persisted across calls to Restart().
void SetTreeMode(bool mode) {m_treeMode=mode;}
/// \brief Get tree mode
/// \returns the current tree mode
/// \details Tree mode is persisted across calls to Restart().
bool GetTreeMode() const {return m_treeMode;}
void TruncatedFinal(byte *hash, size_t size);
std::string AlgorithmProvider() const;
protected:
BLAKE2_Base();
BLAKE2_Base(bool treeMode, unsigned int digestSize);
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);
// Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
void Compress(const byte *input);
inline void IncrementCounter(size_t count=BLOCKSIZE);
void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
private:
AlignedState m_state;
AlignedParameterBlock m_block;
AlignedSecByteBlock m_key;
word32 m_digestSize;
bool m_treeMode;
};
/// \brief The BLAKE2b cryptographic hash function
/// \details BLAKE2b can function as both a hash and keyed hash. If you want only the hash,
/// then use the BLAKE2b constructor that accepts no parameters or digest size. If you
/// want a keyed hash, then use the constructor that accpts the key as a parameter.
/// Once a key and digest size are selected, its effectively immutable. The Restart()
/// method that accepts a ParameterBlock does not allow you to change it.
/// \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
/// <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
/// \since Crypto++ 5.6.4
class BLAKE2b : public BLAKE2_Base<word64, true>
{
public:
typedef BLAKE2_Base<word64, true> ThisBase; // Early Visual Studio workaround
typedef BLAKE2_ParameterBlock<true> ParameterBlock;
CRYPTOPP_COMPILE_ASSERT(sizeof(ParameterBlock) == 64);
/// \brief Construct a BLAKE2b hash
/// \param digestSize the digest size, in bytes
/// \param treeMode flag indicating tree mode
BLAKE2b(bool treeMode=false, unsigned int digestSize = DIGESTSIZE) : ThisBase(treeMode, digestSize) {}
/// \brief Construct a BLAKE2b hash
/// \param key a byte array used to key the cipher
/// \param keyLength the size of the byte array
/// \param salt a byte array used as salt
/// \param saltLength the size of the byte array
/// \param personalization a byte array used as prsonalization string
/// \param personalizationLength the size of the byte array
/// \param treeMode flag indicating tree mode
/// \param digestSize the digest size, in bytes
BLAKE2b(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
const byte* personalization = NULLPTR, size_t personalizationLength = 0,
bool treeMode=false, unsigned int digestSize = DIGESTSIZE)
: ThisBase(key, keyLength, salt, saltLength, personalization, personalizationLength, treeMode, digestSize) {}
// SSE2, SSE4 and NEON depend upon t[] and f[] being side-by-side
word64 h[8], t[2], f[2];
byte buffer[BLAKE2b_Info::BLOCKSIZE];
size_t length;
};
/// \brief The BLAKE2s cryptographic hash function
@ -280,31 +171,194 @@ public:
/// \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
/// <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
/// \since Crypto++ 5.6.4
class BLAKE2s : public BLAKE2_Base<word32, false>
class BLAKE2s : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2s_Info>
{
public:
typedef BLAKE2_Base<word32, false> ThisBase; // Early Visual Studio workaround
typedef BLAKE2_ParameterBlock<false> ParameterBlock;
CRYPTOPP_COMPILE_ASSERT(sizeof(ParameterBlock) == 32);
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2s_Info::DEFAULT_KEYLENGTH)
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2s_Info::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2s_Info::MAX_KEYLENGTH)
/// \brief Construct a BLAKE2s hash
/// \param digestSize the digest size, in bytes
/// \param treeMode flag indicating tree mode
BLAKE2s(bool treeMode=false, unsigned int digestSize = DIGESTSIZE) : ThisBase(treeMode, digestSize) {}
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2s_Info::DIGESTSIZE)
CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2s_Info::BLOCKSIZE)
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2s_Info::SALTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2s_Info::PERSONALIZATIONSIZE)
/// \brief Construct a BLAKE2s hash
/// \param key a byte array used to key the cipher
/// \param keyLength the size of the byte array
/// \param salt a byte array used as salt
/// \param saltLength the size of the byte array
/// \param personalization a byte array used as prsonalization string
/// \param personalizationLength the size of the byte array
/// \param treeMode flag indicating tree mode
/// \param digestSize the digest size, in bytes
BLAKE2s(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
const byte* personalization = NULLPTR, size_t personalizationLength = 0,
bool treeMode=false, unsigned int digestSize = DIGESTSIZE)
: ThisBase(key, keyLength, salt, saltLength, personalization, personalizationLength, treeMode, digestSize) {}
typedef BLAKE2s_State State;
typedef BLAKE2s_ParameterBlock ParameterBlock;
typedef SecBlock<State, AllocatorWithCleanup<State, true> > AlignedState;
typedef SecBlock<ParameterBlock, AllocatorWithCleanup<ParameterBlock, true> > AlignedParameterBlock;
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2s";}
virtual ~BLAKE2s() {}
/// \brief Construct a BLAKE2s hash
/// \param digestSize the digest size, in bytes
/// \param treeMode flag indicating tree mode
BLAKE2s(bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
/// \brief Construct a BLAKE2s hash
/// \param key a byte array used to key the cipher
/// \param keyLength the size of the byte array
/// \param salt a byte array used as salt
/// \param saltLength the size of the byte array
/// \param personalization a byte array used as prsonalization string
/// \param personalizationLength the size of the byte array
/// \param treeMode flag indicating tree mode
/// \param digestSize the digest size, in bytes
BLAKE2s(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
const byte* personalization = NULLPTR, size_t personalizationLength = 0,
bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
/// \brief Retrieve the object's name
/// \returns the object's algorithm name following RFC 7693
/// \details Object algorithm name follows the naming described in
/// <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
/// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
std::string AlgorithmName() const {return std::string(BLAKE2s_Info::StaticAlgorithmName()) + "-" + IntToString(this->DigestSize()*8);}
unsigned int DigestSize() const {return m_digestSize;}
unsigned int OptimalDataAlignment() const {return (CRYPTOPP_BOOL_ALIGN16 ? 16 : GetAlignmentOf<word32>());}
void Update(const byte *input, size_t length);
void Restart();
/// \brief Restart a hash with parameter block and counter
/// \param block parameter block
/// \param counter counter array
/// \details Parameter block is persisted across calls to Restart().
void Restart(const BLAKE2s_ParameterBlock& block, const word32 counter[2]);
/// \brief Set tree mode
/// \param mode the new tree mode
/// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
/// If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
/// <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
/// Tree mode is persisted across calls to Restart().
void SetTreeMode(bool mode) {m_treeMode=mode;}
/// \brief Get tree mode
/// \returns the current tree mode
/// \details Tree mode is persisted across calls to Restart().
bool GetTreeMode() const {return m_treeMode;}
void TruncatedFinal(byte *hash, size_t size);
std::string AlgorithmProvider() const;
protected:
// Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
void Compress(const byte *input);
inline void IncrementCounter(size_t count=BLOCKSIZE);
void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
private:
AlignedState m_state;
AlignedParameterBlock m_block;
AlignedSecByteBlock m_key;
word32 m_digestSize;
bool m_treeMode;
};
/// \brief The BLAKE2b cryptographic hash function
/// \details BLAKE2b can function as both a hash and keyed hash. If you want only the hash,
/// then use the BLAKE2b constructor that accepts no parameters or digest size. If you
/// want a keyed hash, then use the constructor that accpts the key as a parameter.
/// Once a key and digest size are selected, its effectively immutable. The Restart()
/// method that accepts a ParameterBlock does not allow you to change it.
/// \sa Aumasson, Neves, Wilcox-O'Hearn and Winnerlein's
/// <A HREF="http://blake2.net/blake2.pdf">BLAKE2: simpler, smaller, fast as MD5</A> (2013.01.29).
/// \since Crypto++ 5.6.4
class BLAKE2b : public SimpleKeyingInterfaceImpl<MessageAuthenticationCode, BLAKE2b_Info>
{
public:
CRYPTOPP_CONSTANT(DEFAULT_KEYLENGTH = BLAKE2b_Info::DEFAULT_KEYLENGTH)
CRYPTOPP_CONSTANT(MIN_KEYLENGTH = BLAKE2b_Info::MIN_KEYLENGTH)
CRYPTOPP_CONSTANT(MAX_KEYLENGTH = BLAKE2b_Info::MAX_KEYLENGTH)
CRYPTOPP_CONSTANT(DIGESTSIZE = BLAKE2b_Info::DIGESTSIZE)
CRYPTOPP_CONSTANT(BLOCKSIZE = BLAKE2b_Info::BLOCKSIZE)
CRYPTOPP_CONSTANT(SALTSIZE = BLAKE2b_Info::SALTSIZE)
CRYPTOPP_CONSTANT(PERSONALIZATIONSIZE = BLAKE2b_Info::PERSONALIZATIONSIZE)
typedef BLAKE2b_State State;
typedef BLAKE2b_ParameterBlock ParameterBlock;
typedef SecBlock<State, AllocatorWithCleanup<State, true> > AlignedState;
typedef SecBlock<ParameterBlock, AllocatorWithCleanup<ParameterBlock, true> > AlignedParameterBlock;
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() {return "BLAKE2b";}
virtual ~BLAKE2b() {}
/// \brief Construct a BLAKE2b hash
/// \param digestSize the digest size, in bytes
/// \param treeMode flag indicating tree mode
BLAKE2b(bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
/// \brief Construct a BLAKE2b hash
/// \param key a byte array used to key the cipher
/// \param keyLength the size of the byte array
/// \param salt a byte array used as salt
/// \param saltLength the size of the byte array
/// \param personalization a byte array used as prsonalization string
/// \param personalizationLength the size of the byte array
/// \param treeMode flag indicating tree mode
/// \param digestSize the digest size, in bytes
BLAKE2b(const byte *key, size_t keyLength, const byte* salt = NULLPTR, size_t saltLength = 0,
const byte* personalization = NULLPTR, size_t personalizationLength = 0,
bool treeMode=false, unsigned int digestSize = DIGESTSIZE);
/// \brief Retrieve the object's name
/// \returns the object's algorithm name following RFC 7693
/// \details Object algorithm name follows the naming described in
/// <A HREF="http://tools.ietf.org/html/rfc7693#section-4">RFC 7693, The BLAKE2 Cryptographic Hash and
/// Message Authentication Code (MAC)</A>. For example, "BLAKE2b-512" and "BLAKE2s-256".
std::string AlgorithmName() const {return std::string(BLAKE2b_Info::StaticAlgorithmName()) + "-" + IntToString(this->DigestSize()*8);}
unsigned int DigestSize() const {return m_digestSize;}
unsigned int OptimalDataAlignment() const {return (CRYPTOPP_BOOL_ALIGN16 ? 16 : GetAlignmentOf<word64>());}
void Update(const byte *input, size_t length);
void Restart();
/// \brief Restart a hash with parameter block and counter
/// \param block parameter block
/// \param counter counter array
/// \details Parameter block is persisted across calls to Restart().
void Restart(const BLAKE2b_ParameterBlock& block, const word64 counter[2]);
/// \brief Set tree mode
/// \param mode the new tree mode
/// \details BLAKE2 has two finalization flags, called State::f[0] and State::f[1].
/// If <tt>treeMode=false</tt> (default), then State::f[1] is never set. If
/// <tt>treeMode=true</tt>, then State::f[1] is set when State::f[0] is set.
/// Tree mode is persisted across calls to Restart().
void SetTreeMode(bool mode) {m_treeMode=mode;}
/// \brief Get tree mode
/// \returns the current tree mode
/// \details Tree mode is persisted across calls to Restart().
bool GetTreeMode() const {return m_treeMode;}
void TruncatedFinal(byte *hash, size_t size);
std::string AlgorithmProvider() const;
protected:
// Operates on state buffer and/or input. Must be BLOCKSIZE, final block will pad with 0's.
void Compress(const byte *input);
inline void IncrementCounter(size_t count=BLOCKSIZE);
void UncheckedSetKey(const byte* key, unsigned int length, const CryptoPP::NameValuePairs& params);
private:
AlignedState m_state;
AlignedParameterBlock m_block;
AlignedSecByteBlock m_key;
word32 m_digestSize;
bool m_treeMode;
};
NAMESPACE_END

View File

@ -45,27 +45,12 @@
# include "ppc-simd.h"
#endif
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::word32;
using CryptoPP::word64;
#if (CRYPTOPP_SSE41_AVAILABLE || CRYPTOPP_ARM_NEON_AVAILABLE || CRYPTOPP_POWER8_AVAILABLE)
CRYPTOPP_ALIGN_DATA(16)
const word64 BLAKE2B_IV[8] = {
W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)
};
#endif // CRYPTOPP_SSE41_AVAILABLE || CRYPTOPP_ARM_NEON_AVAILABLE
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
// Exported by blake2.cpp
extern const word32 BLAKE2S_IV[8];
extern const word64 BLAKE2B_IV[8];
#if CRYPTOPP_SSE41_AVAILABLE
#define LOADU(p) _mm_loadu_si128( (const __m128i *)(const void*)(p) )
@ -73,7 +58,7 @@ NAMESPACE_BEGIN(CryptoPP)
#define TOF(reg) _mm_castsi128_ps((reg))
#define TOI(reg) _mm_castps_si128((reg))
void BLAKE2_Compress64_SSE4(const byte* input, BLAKE2_State<word64, true>& state)
void BLAKE2_Compress64_SSE4(const byte* input, BLAKE2b_State& state)
{
#define BLAKE2B_LOAD_MSG_0_1(b0, b1) \
do { \
@ -500,7 +485,7 @@ void BLAKE2_Compress64_SSE4(const byte* input, BLAKE2_State<word64, true>& state
#endif // CRYPTOPP_SSE41_AVAILABLE
#if CRYPTOPP_ARM_NEON_AVAILABLE
void BLAKE2_Compress64_NEON(const byte* input, BLAKE2_State<word64, true>& state)
void BLAKE2_Compress64_NEON(const byte* input, BLAKE2b_State& state)
{
#define BLAKE2B_LOAD_MSG_0_1(b0, b1) \
do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m1)); b1 = vcombine_u64(vget_low_u64(m2), vget_low_u64(m3)); } while(0)
@ -823,7 +808,7 @@ inline uint64x2_p VectorShiftLeftOctet(const uint64x2_p a, const uint64x2_p b)
# define vec_merge_lo(a,b) vec_mergel(a,b)
#endif
void BLAKE2_Compress64_POWER8(const byte* input, BLAKE2_State<word64, true>& state)
void BLAKE2_Compress64_POWER8(const byte* input, BLAKE2b_State& state)
{
// Permute masks. High is element 0 (most significant),
// low is element 1 (least significant).

View File

@ -45,25 +45,12 @@
# include "ppc-simd.h"
#endif
ANONYMOUS_NAMESPACE_BEGIN
using CryptoPP::word32;
using CryptoPP::word64;
#if (CRYPTOPP_SSE41_AVAILABLE || CRYPTOPP_ARM_NEON_AVAILABLE || CRYPTOPP_POWER7_AVAILABLE)
CRYPTOPP_ALIGN_DATA(16)
const word32 BLAKE2S_IV[8] = {
0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL,
0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL
};
#endif
ANONYMOUS_NAMESPACE_END
NAMESPACE_BEGIN(CryptoPP)
// Exported by blake2.cpp
extern const word32 BLAKE2S_IV[8];
extern const word64 BLAKE2B_IV[8];
#if CRYPTOPP_SSE41_AVAILABLE
#define LOADU(p) _mm_loadu_si128( (const __m128i *)(const void*)(p) )
@ -71,7 +58,7 @@ NAMESPACE_BEGIN(CryptoPP)
#define TOF(reg) _mm_castsi128_ps((reg))
#define TOI(reg) _mm_castps_si128((reg))
void BLAKE2_Compress32_SSE4(const byte* input, BLAKE2_State<word32, false>& state)
void BLAKE2_Compress32_SSE4(const byte* input, BLAKE2s_State& state)
{
#define BLAKE2S_LOAD_MSG_0_1(buf) \
buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(2,0,2,0)));
@ -367,7 +354,7 @@ void BLAKE2_Compress32_SSE4(const byte* input, BLAKE2_State<word32, false>& stat
#endif // CRYPTOPP_SSE41_AVAILABLE
#if CRYPTOPP_ARM_NEON_AVAILABLE
void BLAKE2_Compress32_NEON(const byte* input, BLAKE2_State<word32, false>& state)
void BLAKE2_Compress32_NEON(const byte* input, BLAKE2s_State& state)
{
#define BLAKE2S_LOAD_MSG_0_1(buf) \
do { uint32x2_t t0, t1; \
@ -656,10 +643,6 @@ void BLAKE2_Compress32_NEON(const byte* input, BLAKE2_State<word32, false>& stat
BLAKE2S_UNDIAGONALIZE(row1,row2,row3,row4); \
} while(0)
CRYPTOPP_ASSERT(IsAlignedOn(&state.h[0],GetAlignmentOf<uint32x4_t>()));
CRYPTOPP_ASSERT(IsAlignedOn(&state.t[0],GetAlignmentOf<uint32x4_t>()));
CRYPTOPP_ASSERT(IsAlignedOn(&state.f[0],GetAlignmentOf<uint32x4_t>()));
const uint32x4_t m0 = vreinterpretq_u32_u8(vld1q_u8((input + 00)));
const uint32x4_t m1 = vreinterpretq_u32_u8(vld1q_u8((input + 16)));
const uint32x4_t m2 = vreinterpretq_u32_u8(vld1q_u8((input + 32)));
@ -880,7 +863,7 @@ uint32x4_p VectorSet32<3,1,3,1>(const uint32x4_p a, const uint32x4_p b,
return vec_perm(a, c, mask);
}
void BLAKE2_Compress32_POWER7(const byte* input, BLAKE2_State<word32, false>& state)
void BLAKE2_Compress32_POWER7(const byte* input, BLAKE2s_State& state)
{
# define m1 m0
# define m2 m0