Enable SIMD implementation for ChaChaTLS (GH #265)

pull/795/head
Jeffrey Walton 2019-01-25 02:57:11 -05:00
parent caaaaa7691
commit d25ba0c59a
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
2 changed files with 57 additions and 66 deletions

View File

@ -337,9 +337,6 @@ std::string ChaChaTLS_Policy::AlgorithmName() const
std::string ChaChaTLS_Policy::AlgorithmProvider() const
{
// Disable SIMD until we obtain large block test vectors and handle wrap.
// https://mailarchive.ietf.org/arch/msg/saag/S0_YjVkzEx2s2bHd8KIzjK1CwZ4
#if 0
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
return "AVX2";
@ -363,7 +360,6 @@ std::string ChaChaTLS_Policy::AlgorithmProvider() const
if (HasAltivec())
return "Altivec";
else
#endif
#endif
return "C++";
}
@ -418,9 +414,6 @@ void ChaChaTLS_Policy::SeekToIteration(lword iterationCount)
unsigned int ChaChaTLS_Policy::GetAlignment() const
{
// Disable SIMD until we obtain large block test vectors and handle wrap.
// https://mailarchive.ietf.org/arch/msg/saag/S0_YjVkzEx2s2bHd8KIzjK1CwZ4
#if 0
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
return 16;
@ -435,16 +428,12 @@ unsigned int ChaChaTLS_Policy::GetAlignment() const
if (HasAltivec())
return 16;
else
#endif
#endif
return GetAlignmentOf<word32>();
}
unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const
{
// Disable SIMD until we obtain large block test vectors and handle wrap.
// https://mailarchive.ietf.org/arch/msg/saag/S0_YjVkzEx2s2bHd8KIzjK1CwZ4
#if 0
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
return 8 * BYTES_PER_ITERATION;
@ -464,32 +453,33 @@ unsigned int ChaChaTLS_Policy::GetOptimalBlockSize() const
if (HasAltivec())
return 4*BYTES_PER_ITERATION;
else
#endif
#endif
return BYTES_PER_ITERATION;
}
bool ChaChaTLS_Policy::MultiBlockSafe(unsigned int blocks) const
{
return 0xffffffff - m_state[12] > blocks;
}
// OperateKeystream always produces a key stream. The key stream is written
// to output. Optionally a message may be supplied to xor with the key stream.
// The message is input, and output = output ^ input.
void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
byte *output, const byte *input, size_t iterationCount)
{
// Disable SIMD until we obtain large block test vectors and handle wrap.
// https://mailarchive.ietf.org/arch/msg/saag/S0_YjVkzEx2s2bHd8KIzjK1CwZ4
#if 0
do
{
#if (CRYPTOPP_AVX2_AVAILABLE)
if (HasAVX2())
{
while (iterationCount >= 8)
while (iterationCount >= 8 && MultiBlockSafe(8))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_AVX2(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// MultiBlockSafe avoids overflow on the counter words
// MultiBlockSafe avoids overflow on the counter word
m_state[12] += 8;
//if (m_state[12] < 8)
// m_state[13]++;
input += (!!xorInput) * 8 * BYTES_PER_ITERATION;
output += 8 * BYTES_PER_ITERATION;
@ -501,15 +491,13 @@ void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
#if (CRYPTOPP_SSE2_INTRIN_AVAILABLE)
if (HasSSE2())
{
while (iterationCount >= 4)
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_SSE2(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// MultiBlockSafe avoids overflow on the counter words
// MultiBlockSafe avoids overflow on the counter word
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
@ -521,15 +509,13 @@ void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
#if (CRYPTOPP_ARM_NEON_AVAILABLE)
if (HasNEON())
{
while (iterationCount >= 4)
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_NEON(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// MultiBlockSafe avoids overflow on the counter words
// MultiBlockSafe avoids overflow on the counter word
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
@ -541,15 +527,13 @@ void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
#if (CRYPTOPP_POWER7_AVAILABLE)
if (HasPower7())
{
while (iterationCount >= 4)
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_POWER7(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// MultiBlockSafe avoids overflow on the counter words
// MultiBlockSafe avoids overflow on the counter word
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
@ -559,25 +543,22 @@ void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
#elif (CRYPTOPP_ALTIVEC_AVAILABLE)
if (HasAltivec())
{
while (iterationCount >= 4)
while (iterationCount >= 4 && MultiBlockSafe(4))
{
const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL;
ChaCha_OperateKeystream_ALTIVEC(m_state, xorInput ? input : NULLPTR, output, m_rounds);
// MultiBlockSafe avoids overflow on the counter words
// MultiBlockSafe avoids overflow on the counter word
m_state[12] += 4;
//if (m_state[12] < 4)
// m_state[13]++;
input += (!!xorInput)*4*BYTES_PER_ITERATION;
output += 4*BYTES_PER_ITERATION;
iterationCount -= 4;
}
}
#endif
#endif
while (iterationCount--)
if (iterationCount)
{
word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
@ -611,6 +592,9 @@ void ChaChaTLS_Policy::OperateKeystream(KeystreamOperation operation,
CRYPTOPP_ASSERT(0);
}
}
// We may re-enter a SIMD keystream operation from here.
} while (iterationCount--);
}
NAMESPACE_END

View File

@ -131,6 +131,13 @@ protected:
std::string AlgorithmName() const;
std::string AlgorithmProvider() const;
// MultiBlockSafe detects a condition that can arise in the SIMD
// implementations where we overflow one of the 32-bit state words
// during addition in an intermediate result. Conditions to trigger
// issue include a user seeks to around 2^32 blocks (256 GB of data).
// https://github.com/weidai11/cryptopp/issues/732
inline bool MultiBlockSafe(unsigned int blocks) const;
FixedSizeAlignedSecBlock<word32, 16+1> m_state;
CRYPTOPP_CONSTANT(m_rounds = ChaChaTLS_Info::ROUNDS)
};