Crypto++ 8.9
Free C++ class library of cryptographic schemes
rabbit.cpp
1// rabbit.cpp - written and placed in the public domain by Jeffrey Walton
2// based on public domain code by Martin Boesgaard, Mette Vesterager,
3// Thomas Pedersen, Jesper Christiansen and Ove Scavenius.
4//
5// The reference materials and source files are available at
6// The eSTREAM Project, http://www.ecrypt.eu.org/stream/e2-rabbit.html.
7
8#include "pch.h"
9#include "config.h"
10
11#include "rabbit.h"
12#include "secblock.h"
13#include "strciphr.h"
14#include "misc.h"
15
16#define WordType word32
17
18#define BYTES_PER_ITERATION 16
19
20#define RABBIT_OUTPUT(x){\
21 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 0, (m_wx[0] ^ (m_wx[5] >> 16) ^ (m_wx[3] << 16)));\
22 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 1, (m_wx[2] ^ (m_wx[7] >> 16) ^ (m_wx[5] << 16)));\
23 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 2, (m_wx[4] ^ (m_wx[1] >> 16) ^ (m_wx[7] << 16)));\
24 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, LITTLE_ENDIAN_ORDER, 3, (m_wx[6] ^ (m_wx[3] >> 16) ^ (m_wx[1] << 16)));}
25
26ANONYMOUS_NAMESPACE_BEGIN
27
28using CryptoPP::word32;
29using CryptoPP::word64;
30using CryptoPP::rotlConstant;
31
32word32 G_func(word32 x)
33{
34#if 0
35 /* Temporary variables */
36 word32 a, b, h, l;
37
38 /* Construct high and low argument for squaring */
39 a = x & 0xFFFF;
40 b = x >> 16;
41
42 /* Calculate high and low result of squaring */
43 h = (((static_cast<word32>(a*a) >> 17U) + static_cast<word32>(a*b)) >> 15U) + b*b;
44 l = x*x;
45
46 /* Return high XOR low */
47 return static_cast<word32>(h^l);
48#endif
49
50 // Thanks to Jack Lloyd for suggesting the 64-bit multiply.
51 word64 z = x;
52 z *= x;
53 return static_cast<word32>((z >> 32) ^ z);
54}
55
56word32 NextState(word32 c[8], word32 x[8], word32 carry)
57{
58 /* Temporary variables */
59 word32 g[8], c_old[8], i;
60
61 /* Save old counter values */
62 for (i = 0; i<8; i++)
63 c_old[i] = c[i];
64
65 /* Calculate new counter values */
66 c[0] = static_cast<word32>(c[0] + 0x4D34D34D + carry);
67 c[1] = static_cast<word32>(c[1] + 0xD34D34D3 + (c[0] < c_old[0]));
68 c[2] = static_cast<word32>(c[2] + 0x34D34D34 + (c[1] < c_old[1]));
69 c[3] = static_cast<word32>(c[3] + 0x4D34D34D + (c[2] < c_old[2]));
70 c[4] = static_cast<word32>(c[4] + 0xD34D34D3 + (c[3] < c_old[3]));
71 c[5] = static_cast<word32>(c[5] + 0x34D34D34 + (c[4] < c_old[4]));
72 c[6] = static_cast<word32>(c[6] + 0x4D34D34D + (c[5] < c_old[5]));
73 c[7] = static_cast<word32>(c[7] + 0xD34D34D3 + (c[6] < c_old[6]));
74 carry = (c[7] < c_old[7]);
75
76 /* Calculate the g-values */
77 for (i = 0; i<8; i++)
78 g[i] = G_func(static_cast<word32>(x[i] + c[i]));
79
80 /* Calculate new state values */
81 x[0] = static_cast<word32>(g[0] + rotlConstant<16>(g[7]) + rotlConstant<16>(g[6]));
82 x[1] = static_cast<word32>(g[1] + rotlConstant<8>(g[0]) + g[7]);
83 x[2] = static_cast<word32>(g[2] + rotlConstant<16>(g[1]) + rotlConstant<16>(g[0]));
84 x[3] = static_cast<word32>(g[3] + rotlConstant<8>(g[2]) + g[1]);
85 x[4] = static_cast<word32>(g[4] + rotlConstant<16>(g[3]) + rotlConstant<16>(g[2]));
86 x[5] = static_cast<word32>(g[5] + rotlConstant<8>(g[4]) + g[3]);
87 x[6] = static_cast<word32>(g[6] + rotlConstant<16>(g[5]) + rotlConstant<16>(g[4]));
88 x[7] = static_cast<word32>(g[7] + rotlConstant<8>(g[6]) + g[5]);
89
90 return carry;
91}
92
93ANONYMOUS_NAMESPACE_END
94
95NAMESPACE_BEGIN(CryptoPP)
96
97void RabbitPolicy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
98{
99 /* Generate four subkeys */
100 CRYPTOPP_UNUSED(params);
101 GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen);
102
103 /* Generate initial state variables */
104 m_mx[0] = m_t[0];
105 m_mx[2] = m_t[1];
106 m_mx[4] = m_t[2];
107 m_mx[6] = m_t[3];
108 m_mx[1] = static_cast<word32>(m_t[3] << 16) | (m_t[2] >> 16);
109 m_mx[3] = static_cast<word32>(m_t[0] << 16) | (m_t[3] >> 16);
110 m_mx[5] = static_cast<word32>(m_t[1] << 16) | (m_t[0] >> 16);
111 m_mx[7] = static_cast<word32>(m_t[2] << 16) | (m_t[1] >> 16);
112
113 /* Generate initial counter values */
114 m_mc[0] = rotlConstant<16>(m_t[2]);
115 m_mc[2] = rotlConstant<16>(m_t[3]);
116 m_mc[4] = rotlConstant<16>(m_t[0]);
117 m_mc[6] = rotlConstant<16>(m_t[1]);
118 m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF);
119 m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF);
120 m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF);
121 m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF);
122
123 /* Clear carry bit */
124 m_mcy = 0;
125
126 /* Iterate the system four times */
127 for (size_t i = 0; i<4; i++)
128 m_mcy = NextState(m_mc, m_mx, m_mcy);
129
130 /* Modify the counters */
131 for (size_t i = 0; i<8; i++)
132 m_mc[i] ^= m_mx[(i + 4) & 0x7];
133
134 /* Copy master instance to work instance */
135 for (size_t i = 0; i<8; i++)
136 {
137 m_wx[i] = m_mx[i];
138 m_wc[i] = m_mc[i];
139 }
140 m_wcy = m_mcy;
141}
142
143void RabbitPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
144{
145 do
146 {
147 /* Iterate the system */
148 m_wcy = NextState(m_wc, m_wx, m_wcy);
149
151
152 } while (--iterationCount);
153}
154
155void RabbitWithIVPolicy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
156{
157 /* Generate four subkeys */
158 CRYPTOPP_UNUSED(params);
159 GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen);
160
161 /* Generate initial state variables */
162 m_mx[0] = m_t[0];
163 m_mx[2] = m_t[1];
164 m_mx[4] = m_t[2];
165 m_mx[6] = m_t[3];
166 m_mx[1] = static_cast<word32>(m_t[3] << 16) | (m_t[2] >> 16);
167 m_mx[3] = static_cast<word32>(m_t[0] << 16) | (m_t[3] >> 16);
168 m_mx[5] = static_cast<word32>(m_t[1] << 16) | (m_t[0] >> 16);
169 m_mx[7] = static_cast<word32>(m_t[2] << 16) | (m_t[1] >> 16);
170
171 /* Generate initial counter values */
172 m_mc[0] = rotlConstant<16>(m_t[2]);
173 m_mc[2] = rotlConstant<16>(m_t[3]);
174 m_mc[4] = rotlConstant<16>(m_t[0]);
175 m_mc[6] = rotlConstant<16>(m_t[1]);
176 m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF);
177 m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF);
178 m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF);
179 m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF);
180
181 /* Clear carry bit */
182 m_mcy = 0;
183
184 /* Iterate the system four times */
185 for (size_t i = 0; i<4; i++)
186 m_mcy = NextState(m_mc, m_mx, m_mcy);
187
188 /* Modify the counters */
189 for (size_t i = 0; i<8; i++)
190 m_mc[i] ^= m_mx[(i + 4) & 0x7];
191
192 /* Copy master instance to work instance */
193 for (size_t i = 0; i<8; i++)
194 {
195 m_wx[i] = m_mx[i];
196 m_wc[i] = m_mc[i];
197 }
198 m_wcy = m_mcy;
199}
200
201void RabbitWithIVPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
202{
203 CRYPTOPP_UNUSED(keystreamBuffer);
204 CRYPTOPP_UNUSED(length);
205 CRYPTOPP_ASSERT(length == 8);
206
207 /* Generate four subvectors */
208 GetBlock<word32, LittleEndian> v(iv); v(m_t[0])(m_t[2]);
209 m_t[1] = (m_t[0] >> 16) | (m_t[2] & 0xFFFF0000);
210 m_t[3] = (m_t[2] << 16) | (m_t[0] & 0x0000FFFF);
211
212 /* Modify counter values */
213 m_wc[0] = m_mc[0] ^ m_t[0];
214 m_wc[1] = m_mc[1] ^ m_t[1];
215 m_wc[2] = m_mc[2] ^ m_t[2];
216 m_wc[3] = m_mc[3] ^ m_t[3];
217 m_wc[4] = m_mc[4] ^ m_t[0];
218 m_wc[5] = m_mc[5] ^ m_t[1];
219 m_wc[6] = m_mc[6] ^ m_t[2];
220 m_wc[7] = m_mc[7] ^ m_t[3];
221
222 /* Copy state variables */
223 for (size_t i = 0; i<8; i++)
224 m_wx[i] = m_mx[i];
225 m_wcy = m_mcy;
226
227 /* Iterate the system four times */
228 for (size_t i = 0; i<4; i++)
229 m_wcy = NextState(m_wc, m_wx, m_wcy);
230}
231
232void RabbitWithIVPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
233{
234 do
235 {
236 /* Iterate the system */
237 m_wcy = NextState(m_wc, m_wx, m_wcy);
238
240
241 } while (--iterationCount);
242}
243
244NAMESPACE_END
Access a block of memory.
Definition misc.h:2975
Interface for retrieving values given their names.
Definition cryptlib.h:327
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition secblock.h:836
Library configuration file.
unsigned int word32
32-bit unsigned datatype
Definition config_int.h:72
unsigned long long word64
64-bit unsigned datatype
Definition config_int.h:101
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition cryptlib.h:150
Utility functions for the Crypto++ library.
void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
Copy bytes in a buffer to an array of elements in big-endian order.
Definition misc.h:2500
Crypto++ library namespace.
Precompiled header file.
Classes for Rabbit stream cipher.
Classes and functions for secure memory allocations.
Classes for implementing stream ciphers.
#define CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(x, y)
Helper macro to implement OperateKeystream.
Definition strciphr.h:266
KeystreamOperation
Keystream operation flags.
Definition strciphr.h:88
static const int BYTES_PER_ITERATION
Number of bytes for an iteration.
Definition strciphr.h:211
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition trap.h:68