From 38f6c33789e1a029595564dd5663622b15410d35 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Thu, 21 Apr 2016 12:12:42 -0400 Subject: [PATCH] Update ChaCha to latest sources --- chacha.cpp | 158 ++++++++++++++++++++++++++--------------------------- chacha.h | 26 +++++---- 2 files changed, 95 insertions(+), 89 deletions(-) mode change 100644 => 100755 chacha.cpp mode change 100644 => 100755 chacha.h diff --git a/chacha.cpp b/chacha.cpp old mode 100644 new mode 100755 index 477bbde2..c5178fe4 --- a/chacha.cpp +++ b/chacha.cpp @@ -1,5 +1,7 @@ // chacha.cpp - written and placed in the public domain by Jeffrey Walton. // Copyright assigned to the Crypto++ project. +// Based on Wei Dai's Salsa20 and Bernstein's reference ChaCha +// family implementation at http://cr.yp.to/chacha.html. #include "pch.h" #include "config.h" @@ -8,96 +10,70 @@ #include "misc.h" #include "cpu.h" -#if CRYPTOPP_MSC_VERSION -# pragma warning(disable: 4702 4740) -#endif - NAMESPACE_BEGIN(CryptoPP) -#define CHACHA_QUARTER_ROUND(z,a,b,c,d) \ - z[a] += z[b]; z[d] ^= z[a]; z[d] = rotrFixed(z[d],16); \ - z[c] += z[d]; z[b] ^= z[c]; z[b] = rotrFixed(z[b],12); \ - z[a] += z[b]; z[d] ^= z[a]; z[d] = rotrFixed(z[d], 8); \ - z[c] += z[d]; z[b] ^= z[c]; z[b] = rotrFixed(z[b], 7); +#define CHACHA_QUARTER_ROUND(a,b,c,d) \ + a += b; d ^= a; d = rotlFixed(d,16); \ + c += d; b ^= c; b = rotlFixed(b,12); \ + a += b; d ^= a; d = rotlFixed(d, 8); \ + c += d; b ^= c; b = rotlFixed(b, 7); #if !defined(NDEBUG) && !defined(CRYPTOPP_DOXYGEN_PROCESSING) void ChaCha_TestInstantiations() { - ChaCha8::Encryption x1; + ChaCha8::Encryption x1; ChaCha12::Encryption x2; ChaCha20::Encryption x3; } #endif - -static inline void salsa20_wordtobyte(byte output[64], const word32 input[16]) -{ - word32 x[16]; - unsigned int i; - - for (i = 0;i < 16;++i) - x[i] = input[i]; - - for (i = 8;i > 0;i -= 2) - { - CHACHA_QUARTER_ROUND(x, 0, 4, 8,12); - CHACHA_QUARTER_ROUND(x, 1, 5, 9,13); - CHACHA_QUARTER_ROUND(x, 2, 6,10,14); - CHACHA_QUARTER_ROUND(x, 3, 7,11,15); - CHACHA_QUARTER_ROUND(x, 0, 5,10,15); - CHACHA_QUARTER_ROUND(x, 1, 6,11,12); - CHACHA_QUARTER_ROUND(x, 2, 7, 8,13); - CHACHA_QUARTER_ROUND(x, 3, 4, 9,14); - } - - for (i = 0;i < 16;++i) - x[i] += input[i]; - - //for (i = 0;i < 16;++i) - // U32TO8_LITTLE(output + 4 * i,x[i]); - - //for (i = 0;i < 16;++i) - // PutWord<>(output + 4 * i,x[i]); -} - template -void ChaCha_Base::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) +void ChaCha_Policy::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length) { - // m_state is reordered for SSE2 - GetBlock get1(key); - get1(m_state[13])(m_state[10])(m_state[7])(m_state[4]); - GetBlock get2(key + length - 16); - get2(m_state[15])(m_state[12])(m_state[9])(m_state[6]); + CRYPTOPP_UNUSED(params); + assert(length == 16 || length == 32); // "expand 16-byte k" or "expand 32-byte k" m_state[0] = 0x61707865; m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e; m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32; m_state[3] = 0x6b206574; + + GetBlock get1(key); + get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]); + + GetBlock get2(key + ((length == 32) ? 16 : 0)); + get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]); } template -void ChaCha_Base::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) +void ChaCha_Policy::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length) { CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length); assert(length==8); GetBlock get(IV); - get(m_state[14])(m_state[11]); - m_state[8] = m_state[5] = 0; + m_state[12] = m_state[13] = 0; + get(m_state[14])(m_state[15]); } template -void ChaCha_Base::SeekToIteration(lword iterationCount) +void ChaCha_Policy::SeekToIteration(lword iterationCount) { - m_state[8] = (word32)iterationCount; - m_state[5] = (word32)SafeRightShift<32>(iterationCount); + CRYPTOPP_UNUSED(iterationCount); + throw NotImplemented(std::string(ChaCha_Info::StaticAlgorithmName()) + ": SeekToIteration is not yet implemented"); + + // TODO: these were Salsa20, and Wei re-arranged the state array for SSE2 operations. + // If we can generate some out-of-band test vectors, then test and implement. Also + // see the test vectors in salsa.txt and the use of Seek test argument. + // m_state[8] = (word32)iterationCount; + // m_state[5] = (word32)SafeRightShift<32>(iterationCount); } template -unsigned int ChaCha_Base::GetAlignment() const +unsigned int ChaCha_Policy::GetAlignment() const { -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && 0 if (HasSSE2()) return 16; else @@ -106,9 +82,9 @@ unsigned int ChaCha_Base::GetAlignment() const } template -unsigned int ChaCha_Base::GetOptimalBlockSize() const +unsigned int ChaCha_Policy::GetOptimalBlockSize() const { -#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE +#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && 0 if (HasSSE2()) return 4*BYTES_PER_ITERATION; else @@ -117,36 +93,60 @@ unsigned int ChaCha_Base::GetOptimalBlockSize() const } template -void ChaCha_Base::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) +void ChaCha_Policy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount) { - byte buffer[64]; - size_t i, bytes=64; + word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15; - if (!bytes) return; - - for (;;) + while (iterationCount--) { - salsa20_wordtobyte(buffer,m_state); + x0 = m_state[0]; x1 = m_state[1]; x2 = m_state[2]; x3 = m_state[3]; + x4 = m_state[4]; x5 = m_state[5]; x6 = m_state[6]; x7 = m_state[7]; + x8 = m_state[8]; x9 = m_state[9]; x10 = m_state[10]; x11 = m_state[11]; + x12 = m_state[12]; x13 = m_state[13]; x14 = m_state[14]; x15 = m_state[15]; - m_state[12]++; - if (!m_state[12]) - m_state[13]++; - - if (bytes <= 64) + for (int i = static_cast(ROUNDS); i > 0; i -= 2) { - for (i = 0;i < bytes;++i) - output[i] = input[i] ^ buffer[i]; - return; + CHACHA_QUARTER_ROUND(x0, x4, x8, x12); + CHACHA_QUARTER_ROUND(x1, x5, x9, x13); + CHACHA_QUARTER_ROUND(x2, x6, x10, x14); + CHACHA_QUARTER_ROUND(x3, x7, x11, x15); + + CHACHA_QUARTER_ROUND(x0, x5, x10, x15); + CHACHA_QUARTER_ROUND(x1, x6, x11, x12); + CHACHA_QUARTER_ROUND(x2, x7, x8, x13); + CHACHA_QUARTER_ROUND(x3, x4, x9, x14); } - for (i = 0;i < 64;++i) - output[i] = input[i] ^ buffer[i]; - - bytes -= 64; - output += 64; - input += 64; + #define CHACHA_OUTPUT(x){\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + m_state[0]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + m_state[1]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + m_state[2]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + m_state[3]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + m_state[4]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + m_state[5]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + m_state[6]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + m_state[7]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + m_state[8]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + m_state[9]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + m_state[10]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + m_state[11]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + m_state[12]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + m_state[13]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + m_state[14]);\ + CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + m_state[15]);} + +#ifndef CRYPTOPP_DOXYGEN_PROCESSING + CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION); +#endif + + if (++m_state[12] == 0) + ++m_state[13]; } } +template class ChaCha_Policy<8>; +template class ChaCha_Policy<12>; +template class ChaCha_Policy<20>; + NAMESPACE_END - \ No newline at end of file + diff --git a/chacha.h b/chacha.h old mode 100644 new mode 100755 index 9a07467a..23608070 --- a/chacha.h +++ b/chacha.h @@ -1,8 +1,10 @@ // chacha.h - written and placed in the public domain by Jeffrey Walton. // Copyright assigned to the Crypto++ project. +// Based on Wei Dai's Salsa20 and Bernstein's reference ChaCha +// family implementation at http://cr.yp.to/chacha.html. //! \file chacha.h -//! \brief Classes for ChaCha8, ChaCha12 and ChaCha stream ciphers +//! \brief Classes for ChaCha8, ChaCha12 and ChaCha20 stream ciphers #ifndef CRYPTOPP_CHACHA_H #define CRYPTOPP_CHACHA_H @@ -17,17 +19,21 @@ NAMESPACE_BEGIN(CryptoPP) template struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8>, public FixedRounds { - static const char *StaticAlgorithmName() {return "ChaCha";} + static const char *StaticAlgorithmName() {static const std::string name = "ChaCha" + IntToString(R); return name.c_str();} }; +//! \class ChaCha_Policy +//! \brief ChaCha stream cipher implementation template -class CRYPTOPP_NO_VTABLE ChaCha_Base : public AdditiveCipherConcretePolicy +class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy { protected: + CRYPTOPP_CONSTANT(ROUNDS=FixedRounds::ROUNDS); + void CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length); void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount); void CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length); - bool CipherIsRandomAccess() const {return true;} + bool CipherIsRandomAccess() const {return false;} // TODO void SeekToIteration(lword iterationCount); unsigned int GetAlignment() const; unsigned int GetOptimalBlockSize() const; @@ -40,8 +46,8 @@ protected: //! \sa ChaCha, a variant of Salsa20 (2008.01.28). struct ChaCha8 : public ChaCha_Info<8>, public SymmetricCipherDocumentation { - typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Encryption; - typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Decryption; + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Encryption; + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Decryption; }; //! \class ChaCha12 @@ -49,8 +55,8 @@ struct ChaCha8 : public ChaCha_Info<8>, public SymmetricCipherDocumentation //! \sa ChaCha, a variant of Salsa20 (2008.01.28). struct ChaCha12 : public ChaCha_Info<12>, public SymmetricCipherDocumentation { - typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Encryption; - typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Decryption; + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Encryption; + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Decryption; }; //! \class ChaCha20 @@ -58,8 +64,8 @@ struct ChaCha12 : public ChaCha_Info<12>, public SymmetricCipherDocumentation //! \sa ChaCha, a variant of Salsa20 (2008.01.28). struct ChaCha20 : public ChaCha_Info<20>, public SymmetricCipherDocumentation { - typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Encryption; - typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Decryption; + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Encryption; + typedef SymmetricCipherFinal, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Decryption; }; NAMESPACE_END