diff --git a/chacha.cpp b/chacha.cpp index a89fa016..05075b17 100644 --- a/chacha.cpp +++ b/chacha.cpp @@ -25,6 +25,8 @@ extern void ChaCha_OperateKeystream_AVX2(const word32 *state, const byte* input, #endif #if (CRYPTOPP_ALTIVEC_AVAILABLE) +// ChaCha_OperateKeystream_POWER7 may be compiled with either -mcpu=power7 or +// -mcpu=power4. The makefile drops to POWER4 if POWER7 is not available. extern void ChaCha_OperateKeystream_POWER7(const word32 *state, const byte* input, byte *output, unsigned int rounds); #endif @@ -85,8 +87,7 @@ std::string ChaCha_Policy::AlgorithmProvider() const if (HasPower7()) return "Power7"; else -#endif -#if (CRYPTOPP_ALTIVEC_AVAILABLE) +#elif (CRYPTOPP_ALTIVEC_AVAILABLE) if (HasAltivec()) return "Altivec"; else @@ -250,11 +251,31 @@ void ChaCha_Policy::OperateKeystream(KeystreamOperation operation, } #endif -#if (CRYPTOPP_ALTIVEC_AVAILABLE) +#if (CRYPTOPP_POWER7_AVAILABLE) + if (HasPower7()) + { + while (iterationCount >= 4 && MultiBlockSafe(4)) + { + // ChaCha_OperateKeystream_POWER7 compiled with -mcpu=power7 and -DCRYPTOPP_POWER7_AVAILABLE + 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 + 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; + } + } +#elif (CRYPTOPP_ALTIVEC_AVAILABLE) if (HasAltivec()) { while (iterationCount >= 4 && MultiBlockSafe(4)) { + // ChaCha_OperateKeystream_POWER7 compiled with -mcpu=power4 and -DCRYPTOPP_ALTIVEC_AVAILABLE const bool xorInput = (operation & INPUT_NULL) != INPUT_NULL; ChaCha_OperateKeystream_POWER7(m_state, xorInput ? input : NULLPTR, output, m_rounds);