source: trunk/src-cryptopp/chacha.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 5.5 KB
Line 
1// chacha.cpp - written and placed in the public domain by Jeffrey Walton.
2//              Copyright assigned to the Crypto++ project.
3//              Based on Wei Dai's Salsa20 and Bernstein's reference ChaCha
4//              family implementation at http://cr.yp.to/chacha.html.
5
6#include "pch.h"
7#include "config.h"
8#include "chacha.h"
9#include "argnames.h"
10#include "misc.h"
11#include "cpu.h"
12
13NAMESPACE_BEGIN(CryptoPP)
14
15#define CHACHA_QUARTER_ROUND(a,b,c,d) \
16    a += b; d ^= a; d = rotlFixed<word32>(d,16); \
17    c += d; b ^= c; b = rotlFixed<word32>(b,12); \
18    a += b; d ^= a; d = rotlFixed<word32>(d, 8); \
19    c += d; b ^= c; b = rotlFixed<word32>(b, 7);
20
21#if CRYPTOPP_DEBUG && !defined(CRYPTOPP_DOXYGEN_PROCESSING)
22void ChaCha_TestInstantiations()
23{
24         ChaCha8::Encryption x1;
25        ChaCha12::Encryption x2;
26        ChaCha20::Encryption x3;
27}
28#endif
29
30template <unsigned int R>
31void ChaCha_Policy<R>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
32{
33        CRYPTOPP_UNUSED(params);
34        CRYPTOPP_ASSERT(length == 16 || length == 32);
35
36        // "expand 16-byte k" or "expand 32-byte k"
37        m_state[0] = 0x61707865;
38        m_state[1] = (length == 16) ? 0x3120646e : 0x3320646e;
39        m_state[2] = (length == 16) ? 0x79622d36 : 0x79622d32;
40        m_state[3] = 0x6b206574;
41
42        GetBlock<word32, LittleEndian> get1(key);
43        get1(m_state[4])(m_state[5])(m_state[6])(m_state[7]);
44
45        GetBlock<word32, LittleEndian> get2(key + ((length == 32) ? 16 : 0));
46        get2(m_state[8])(m_state[9])(m_state[10])(m_state[11]);
47}
48
49template <unsigned int R>
50void ChaCha_Policy<R>::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
51{
52        CRYPTOPP_UNUSED(keystreamBuffer), CRYPTOPP_UNUSED(length);
53        CRYPTOPP_ASSERT(length==8);
54
55        GetBlock<word32, LittleEndian> get(IV);
56        m_state[12] = m_state[13] = 0;
57        get(m_state[14])(m_state[15]);
58}
59
60template<unsigned int R>
61void ChaCha_Policy<R>::SeekToIteration(lword iterationCount)
62{
63        CRYPTOPP_UNUSED(iterationCount);
64        throw NotImplemented(std::string(ChaCha_Info<R>::StaticAlgorithmName()) + ":  SeekToIteration is not yet implemented");
65
66        // TODO: these were Salsa20, and Wei re-arranged the state array for SSE2 operations.
67        // If we can generate some out-of-band test vectors, then test and implement. Also
68        //  see the test vectors in salsa.txt and the use of Seek test argument.
69        // m_state[8] = (word32)iterationCount;
70        // m_state[5] = (word32)SafeRightShift<32>(iterationCount);
71}
72
73template<unsigned int R>
74unsigned int ChaCha_Policy<R>::GetAlignment() const
75{
76#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && 0
77        if (HasSSE2())
78                return 16;
79        else
80#endif
81                return GetAlignmentOf<word32>();
82}
83
84template<unsigned int R>
85unsigned int ChaCha_Policy<R>::GetOptimalBlockSize() const
86{
87#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && 0
88        if (HasSSE2())
89                return 4*BYTES_PER_ITERATION;
90        else
91#endif
92                return BYTES_PER_ITERATION;
93}
94
95template<unsigned int R>
96void ChaCha_Policy<R>::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
97{
98        word32 x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15;
99
100        while (iterationCount--)
101        {
102                x0 = m_state[0];        x1 = m_state[1];        x2 = m_state[2];        x3 = m_state[3];
103                x4 = m_state[4];        x5 = m_state[5];        x6 = m_state[6];        x7 = m_state[7];
104                x8 = m_state[8];        x9 = m_state[9];        x10 = m_state[10];      x11 = m_state[11];
105                x12 = m_state[12];      x13 = m_state[13];      x14 = m_state[14];      x15 = m_state[15];
106
107                for (int i = static_cast<int>(ROUNDS); i > 0; i -= 2)
108                {
109                        CHACHA_QUARTER_ROUND(x0, x4,  x8, x12);
110                        CHACHA_QUARTER_ROUND(x1, x5,  x9, x13);
111                        CHACHA_QUARTER_ROUND(x2, x6, x10, x14);
112                        CHACHA_QUARTER_ROUND(x3, x7, x11, x15);
113
114                        CHACHA_QUARTER_ROUND(x0, x5, x10, x15);
115                        CHACHA_QUARTER_ROUND(x1, x6, x11, x12);
116                        CHACHA_QUARTER_ROUND(x2, x7,  x8, x13);
117                        CHACHA_QUARTER_ROUND(x3, x4,  x9, x14);
118                }
119
120                #undef CHACHA_OUTPUT
121                #define CHACHA_OUTPUT(x){\
122                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, x0 + m_state[0]);\
123                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, x1 + m_state[1]);\
124                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, x2 + m_state[2]);\
125                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, x3 + m_state[3]);\
126                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 4, x4 + m_state[4]);\
127                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 5, x5 + m_state[5]);\
128                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 6, x6 + m_state[6]);\
129                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 7, x7 + m_state[7]);\
130                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 8, x8 + m_state[8]);\
131                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 9, x9 + m_state[9]);\
132                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 10, x10 + m_state[10]);\
133                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 11, x11 + m_state[11]);\
134                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 12, x12 + m_state[12]);\
135                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 13, x13 + m_state[13]);\
136                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 14, x14 + m_state[14]);\
137                        CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 15, x15 + m_state[15]);}
138
139#ifndef CRYPTOPP_DOXYGEN_PROCESSING
140                CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(CHACHA_OUTPUT, BYTES_PER_ITERATION);
141#endif
142
143                ++m_state[12];
144                m_state[13] += static_cast<word32>(m_state[12] == 0);
145        }
146}
147
148template class ChaCha_Policy<8>;
149template class ChaCha_Policy<12>;
150template class ChaCha_Policy<20>;
151
152NAMESPACE_END
153
Note: See TracBrowser for help on using the repository browser.