mirror of
https://github.com/shadps4-emu/ext-cryptopp.git
synced 2024-11-26 19:30:21 +00:00
Rewrite BLAKE2 classes to remove intermediate base class
This commit is contained in:
parent
06867e5caf
commit
600e2a8be4
318
blake2.cpp
318
blake2.cpp
@ -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
522
blake2.h
@ -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
|
||||
|
@ -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).
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user