Update ChaCha to latest sources
parent
0f702accfc
commit
38f6c33789
|
|
@ -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<word32>(z[d],16); \
|
||||
z[c] += z[d]; z[b] ^= z[c]; z[b] = rotrFixed<word32>(z[b],12); \
|
||||
z[a] += z[b]; z[d] ^= z[a]; z[d] = rotrFixed<word32>(z[d], 8); \
|
||||
z[c] += z[d]; z[b] ^= z[c]; z[b] = rotrFixed<word32>(z[b], 7);
|
||||
#define CHACHA_QUARTER_ROUND(a,b,c,d) \
|
||||
a += b; d ^= a; d = rotlFixed<word32>(d,16); \
|
||||
c += d; b ^= c; b = rotlFixed<word32>(b,12); \
|
||||
a += b; d ^= a; d = rotlFixed<word32>(d, 8); \
|
||||
c += d; b ^= c; b = rotlFixed<word32>(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 <unsigned int R>
|
||||
void ChaCha_Base<R>::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
|
||||
void ChaCha_Policy<R>::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
|
||||
{
|
||||
// m_state is reordered for SSE2
|
||||
GetBlock<word32, LittleEndian> get1(key);
|
||||
get1(m_state[13])(m_state[10])(m_state[7])(m_state[4]);
|
||||
GetBlock<word32, LittleEndian> 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<word32, LittleEndian> get1(key);
|
||||
get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
|
||||
|
||||
GetBlock<word32, LittleEndian> get2(key + ((length == 32) ? 16 : 0));
|
||||
get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
|
||||
}
|
||||
|
||||
template <unsigned int R>
|
||||
void ChaCha_Base<R>::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
|
||||
void ChaCha_Policy<R>::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
|
||||
{
|
||||
CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
|
||||
assert(length==8);
|
||||
|
||||
GetBlock<word32, LittleEndian> 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<unsigned int R>
|
||||
void ChaCha_Base<R>::SeekToIteration(lword iterationCount)
|
||||
void ChaCha_Policy<R>::SeekToIteration(lword iterationCount)
|
||||
{
|
||||
m_state[8] = (word32)iterationCount;
|
||||
m_state[5] = (word32)SafeRightShift<32>(iterationCount);
|
||||
CRYPTOPP_UNUSED(iterationCount);
|
||||
throw NotImplemented(std::string(ChaCha_Info<R>::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 R>
|
||||
unsigned int ChaCha_Base<R>::GetAlignment() const
|
||||
unsigned int ChaCha_Policy<R>::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<R>::GetAlignment() const
|
|||
}
|
||||
|
||||
template<unsigned int R>
|
||||
unsigned int ChaCha_Base<R>::GetOptimalBlockSize() const
|
||||
unsigned int ChaCha_Policy<R>::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<R>::GetOptimalBlockSize() const
|
|||
}
|
||||
|
||||
template<unsigned int R>
|
||||
void ChaCha_Base<R>::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
|
||||
void ChaCha_Policy<R>::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<int>(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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <unsigned int R>
|
||||
struct ChaCha_Info : public VariableKeyLength<32, 16, 32, 16, SimpleKeyingInterface::UNIQUE_IV, 8>, public FixedRounds<R>
|
||||
{
|
||||
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 <unsigned int R>
|
||||
class CRYPTOPP_NO_VTABLE ChaCha_Base : public AdditiveCipherConcretePolicy<word32, 16>
|
||||
class CRYPTOPP_NO_VTABLE ChaCha_Policy : public AdditiveCipherConcretePolicy<word32, 16>
|
||||
{
|
||||
protected:
|
||||
CRYPTOPP_CONSTANT(ROUNDS=FixedRounds<R>::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 <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
|
||||
struct ChaCha8 : public ChaCha_Info<8>, public SymmetricCipherDocumentation
|
||||
{
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Base<8>, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Encryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Base<8>, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Decryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<8>, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Encryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<8>, AdditiveCipherTemplate<> >, ChaCha_Info<8> > Decryption;
|
||||
};
|
||||
|
||||
//! \class ChaCha12
|
||||
|
|
@ -49,8 +55,8 @@ struct ChaCha8 : public ChaCha_Info<8>, public SymmetricCipherDocumentation
|
|||
//! \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
|
||||
struct ChaCha12 : public ChaCha_Info<12>, public SymmetricCipherDocumentation
|
||||
{
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Base<12>, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Encryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Base<12>, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Decryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<12>, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Encryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<12>, AdditiveCipherTemplate<> >, ChaCha_Info<12> > Decryption;
|
||||
};
|
||||
|
||||
//! \class ChaCha20
|
||||
|
|
@ -58,8 +64,8 @@ struct ChaCha12 : public ChaCha_Info<12>, public SymmetricCipherDocumentation
|
|||
//! \sa <a href="http://cr.yp.to/chacha/chacha-20080128.pdf">ChaCha, a variant of Salsa20</a> (2008.01.28).
|
||||
struct ChaCha20 : public ChaCha_Info<20>, public SymmetricCipherDocumentation
|
||||
{
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Base<20>, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Encryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Base<20>, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Decryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<20>, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Encryption;
|
||||
typedef SymmetricCipherFinal<ConcretePolicyHolder<ChaCha_Policy<20>, AdditiveCipherTemplate<> >, ChaCha_Info<20> > Decryption;
|
||||
};
|
||||
|
||||
NAMESPACE_END
|
||||
|
|
|
|||
Loading…
Reference in New Issue