Crypto++  8.8
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 "misc.h"
14 
15 ANONYMOUS_NAMESPACE_BEGIN
16 
17 using CryptoPP::word32;
18 using CryptoPP::word64;
20 
21 word32 G_func(word32 x)
22 {
23 #if 0
24  /* Temporary variables */
25  word32 a, b, h, l;
26 
27  /* Construct high and low argument for squaring */
28  a = x & 0xFFFF;
29  b = x >> 16;
30 
31  /* Calculate high and low result of squaring */
32  h = (((static_cast<word32>(a*a) >> 17U) + static_cast<word32>(a*b)) >> 15U) + b*b;
33  l = x*x;
34 
35  /* Return high XOR low */
36  return static_cast<word32>(h^l);
37 #endif
38 
39  // Thanks to Jack Lloyd for suggesting the 64-bit multiply.
40  word64 z = x;
41  z *= x;
42  return static_cast<word32>((z >> 32) ^ z);
43 }
44 
45 word32 NextState(word32 c[8], word32 x[8], word32 carry)
46 {
47  /* Temporary variables */
48  word32 g[8], c_old[8], i;
49 
50  /* Save old counter values */
51  for (i = 0; i<8; i++)
52  c_old[i] = c[i];
53 
54  /* Calculate new counter values */
55  c[0] = static_cast<word32>(c[0] + 0x4D34D34D + carry);
56  c[1] = static_cast<word32>(c[1] + 0xD34D34D3 + (c[0] < c_old[0]));
57  c[2] = static_cast<word32>(c[2] + 0x34D34D34 + (c[1] < c_old[1]));
58  c[3] = static_cast<word32>(c[3] + 0x4D34D34D + (c[2] < c_old[2]));
59  c[4] = static_cast<word32>(c[4] + 0xD34D34D3 + (c[3] < c_old[3]));
60  c[5] = static_cast<word32>(c[5] + 0x34D34D34 + (c[4] < c_old[4]));
61  c[6] = static_cast<word32>(c[6] + 0x4D34D34D + (c[5] < c_old[5]));
62  c[7] = static_cast<word32>(c[7] + 0xD34D34D3 + (c[6] < c_old[6]));
63  carry = (c[7] < c_old[7]);
64 
65  /* Calculate the g-values */
66  for (i = 0; i<8; i++)
67  g[i] = G_func(static_cast<word32>(x[i] + c[i]));
68 
69  /* Calculate new state values */
70  x[0] = static_cast<word32>(g[0] + rotlConstant<16>(g[7]) + rotlConstant<16>(g[6]));
71  x[1] = static_cast<word32>(g[1] + rotlConstant<8>(g[0]) + g[7]);
72  x[2] = static_cast<word32>(g[2] + rotlConstant<16>(g[1]) + rotlConstant<16>(g[0]));
73  x[3] = static_cast<word32>(g[3] + rotlConstant<8>(g[2]) + g[1]);
74  x[4] = static_cast<word32>(g[4] + rotlConstant<16>(g[3]) + rotlConstant<16>(g[2]));
75  x[5] = static_cast<word32>(g[5] + rotlConstant<8>(g[4]) + g[3]);
76  x[6] = static_cast<word32>(g[6] + rotlConstant<16>(g[5]) + rotlConstant<16>(g[4]));
77  x[7] = static_cast<word32>(g[7] + rotlConstant<8>(g[6]) + g[5]);
78 
79  return carry;
80 }
81 
82 ANONYMOUS_NAMESPACE_END
83 
84 NAMESPACE_BEGIN(CryptoPP)
85 
86 void RabbitPolicy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
87 {
88  /* Generate four subkeys */
89  CRYPTOPP_UNUSED(params);
90  GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen);
91 
92  /* Generate initial state variables */
93  m_mx[0] = m_t[0];
94  m_mx[2] = m_t[1];
95  m_mx[4] = m_t[2];
96  m_mx[6] = m_t[3];
97  m_mx[1] = static_cast<word32>(m_t[3] << 16) | (m_t[2] >> 16);
98  m_mx[3] = static_cast<word32>(m_t[0] << 16) | (m_t[3] >> 16);
99  m_mx[5] = static_cast<word32>(m_t[1] << 16) | (m_t[0] >> 16);
100  m_mx[7] = static_cast<word32>(m_t[2] << 16) | (m_t[1] >> 16);
101 
102  /* Generate initial counter values */
103  m_mc[0] = rotlConstant<16>(m_t[2]);
104  m_mc[2] = rotlConstant<16>(m_t[3]);
105  m_mc[4] = rotlConstant<16>(m_t[0]);
106  m_mc[6] = rotlConstant<16>(m_t[1]);
107  m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF);
108  m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF);
109  m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF);
110  m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF);
111 
112  /* Clear carry bit */
113  m_mcy = 0;
114 
115  /* Iterate the system four times */
116  for (unsigned int i = 0; i<4; i++)
117  m_mcy = NextState(m_mc, m_mx, m_mcy);
118 
119  /* Modify the counters */
120  for (unsigned int i = 0; i<8; i++)
121  m_mc[i] ^= m_mx[(i + 4) & 0x7];
122 
123  /* Copy master instance to work instance */
124  for (unsigned int i = 0; i<8; i++)
125  {
126  m_wx[i] = m_mx[i];
127  m_wc[i] = m_mc[i];
128  }
129  m_wcy = m_mcy;
130 }
131 
132 void RabbitPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
133 {
134  byte* out = output;
135  for (size_t i = 0; i<iterationCount; ++i, out += 16)
136  {
137  /* Iterate the system */
138  m_wcy = NextState(m_wc, m_wx, m_wcy);
139 
140  /* Encrypt/decrypt 16 bytes of data */
141  PutWord(false, LITTLE_ENDIAN_ORDER, out + 0, m_wx[0] ^ (m_wx[5] >> 16) ^ (m_wx[3] << 16));
142  PutWord(false, LITTLE_ENDIAN_ORDER, out + 4, m_wx[2] ^ (m_wx[7] >> 16) ^ (m_wx[5] << 16));
143  PutWord(false, LITTLE_ENDIAN_ORDER, out + 8, m_wx[4] ^ (m_wx[1] >> 16) ^ (m_wx[7] << 16));
144  PutWord(false, LITTLE_ENDIAN_ORDER, out + 12, m_wx[6] ^ (m_wx[3] >> 16) ^ (m_wx[1] << 16));
145  }
146 
147  // If AdditiveCipherTemplate does not have an accumulated keystream
148  // then it will ask OperateKeystream to generate one. Optionally it
149  // will ask for an XOR of the input with the keystream while
150  // writing the result to the output buffer. In all cases the
151  // keystream is written to the output buffer. The optional part is
152  // adding the input buffer and keystream.
153  if ((operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL))
154  xorbuf(output, input, GetBytesPerIteration() * iterationCount);
155 }
156 
157 void RabbitWithIVPolicy::CipherSetKey(const NameValuePairs &params, const byte *userKey, size_t keylen)
158 {
159  /* Generate four subkeys */
160  CRYPTOPP_UNUSED(params);
161  GetUserKey(LITTLE_ENDIAN_ORDER, m_t.begin(), 4, userKey, keylen);
162 
163  /* Generate initial state variables */
164  m_mx[0] = m_t[0];
165  m_mx[2] = m_t[1];
166  m_mx[4] = m_t[2];
167  m_mx[6] = m_t[3];
168  m_mx[1] = static_cast<word32>(m_t[3] << 16) | (m_t[2] >> 16);
169  m_mx[3] = static_cast<word32>(m_t[0] << 16) | (m_t[3] >> 16);
170  m_mx[5] = static_cast<word32>(m_t[1] << 16) | (m_t[0] >> 16);
171  m_mx[7] = static_cast<word32>(m_t[2] << 16) | (m_t[1] >> 16);
172 
173  /* Generate initial counter values */
174  m_mc[0] = rotlConstant<16>(m_t[2]);
175  m_mc[2] = rotlConstant<16>(m_t[3]);
176  m_mc[4] = rotlConstant<16>(m_t[0]);
177  m_mc[6] = rotlConstant<16>(m_t[1]);
178  m_mc[1] = (m_t[0] & 0xFFFF0000) | (m_t[1] & 0xFFFF);
179  m_mc[3] = (m_t[1] & 0xFFFF0000) | (m_t[2] & 0xFFFF);
180  m_mc[5] = (m_t[2] & 0xFFFF0000) | (m_t[3] & 0xFFFF);
181  m_mc[7] = (m_t[3] & 0xFFFF0000) | (m_t[0] & 0xFFFF);
182 
183  /* Clear carry bit */
184  m_mcy = 0;
185 
186  /* Iterate the system four times */
187  for (unsigned int i = 0; i<4; i++)
188  m_mcy = NextState(m_mc, m_mx, m_mcy);
189 
190  /* Modify the counters */
191  for (unsigned int i = 0; i<8; i++)
192  m_mc[i] ^= m_mx[(i + 4) & 0x7];
193 
194  /* Copy master instance to work instance */
195  for (unsigned int i = 0; i<8; i++)
196  {
197  m_wx[i] = m_mx[i];
198  m_wc[i] = m_mc[i];
199  }
200  m_wcy = m_mcy;
201 }
202 
203 void RabbitWithIVPolicy::CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
204 {
205  CRYPTOPP_UNUSED(keystreamBuffer);
206  CRYPTOPP_UNUSED(length);
207  CRYPTOPP_ASSERT(length == 8);
208 
209  /* Generate four subvectors */
210  GetBlock<word32, LittleEndian> v(iv); v(m_t[0])(m_t[2]);
211  m_t[1] = (m_t[0] >> 16) | (m_t[2] & 0xFFFF0000);
212  m_t[3] = (m_t[2] << 16) | (m_t[0] & 0x0000FFFF);
213 
214  /* Modify counter values */
215  m_wc[0] = m_mc[0] ^ m_t[0];
216  m_wc[1] = m_mc[1] ^ m_t[1];
217  m_wc[2] = m_mc[2] ^ m_t[2];
218  m_wc[3] = m_mc[3] ^ m_t[3];
219  m_wc[4] = m_mc[4] ^ m_t[0];
220  m_wc[5] = m_mc[5] ^ m_t[1];
221  m_wc[6] = m_mc[6] ^ m_t[2];
222  m_wc[7] = m_mc[7] ^ m_t[3];
223 
224  /* Copy state variables */
225  for (unsigned int i = 0; i<8; i++)
226  m_wx[i] = m_mx[i];
227  m_wcy = m_mcy;
228 
229  /* Iterate the system four times */
230  for (unsigned int i = 0; i<4; i++)
231  m_wcy = NextState(m_wc, m_wx, m_wcy);
232 }
233 
234 void RabbitWithIVPolicy::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
235 {
236  byte* out = output;
237  for (unsigned int i = 0; i<iterationCount; ++i, out += 16)
238  {
239  /* Iterate the system */
240  m_wcy = NextState(m_wc, m_wx, m_wcy);
241 
242  /* Encrypt/decrypt 16 bytes of data */
243  PutWord(false, LITTLE_ENDIAN_ORDER, out + 0, m_wx[0] ^ (m_wx[5] >> 16) ^ (m_wx[3] << 16));
244  PutWord(false, LITTLE_ENDIAN_ORDER, out + 4, m_wx[2] ^ (m_wx[7] >> 16) ^ (m_wx[5] << 16));
245  PutWord(false, LITTLE_ENDIAN_ORDER, out + 8, m_wx[4] ^ (m_wx[1] >> 16) ^ (m_wx[7] << 16));
246  PutWord(false, LITTLE_ENDIAN_ORDER, out + 12, m_wx[6] ^ (m_wx[3] >> 16) ^ (m_wx[1] << 16));
247  }
248 
249  // If AdditiveCipherTemplate does not have an accumulated keystream
250  // then it will ask OperateKeystream to generate one. Optionally it
251  // will ask for an XOR of the input with the keystream while
252  // writing the result to the output buffer. In all cases the
253  // keystream is written to the output buffer. The optional part is
254  // adding the input buffer and keystream.
255  if ((operation & EnumToInt(INPUT_NULL)) != EnumToInt(INPUT_NULL))
256  xorbuf(output, input, GetBytesPerIteration() * iterationCount);
257 }
258 
259 NAMESPACE_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.
T rotlConstant(T x)
Performs a left rotate.
Definition: misc.h:1757
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
#define EnumToInt(v)
Integer value.
Definition: misc.h:504
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULL)
Access a block of memory.
Definition: misc.h:2948
CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Crypto++ library namespace.
Precompiled header file.
Classes for Rabbit stream cipher.
Classes and functions for secure memory allocations.
KeystreamOperation
Keystream operation flags.
Definition: strciphr.h:88
@ INPUT_NULL
Input buffer is NULL.
Definition: strciphr.h:82
unsigned int GetBytesPerIteration() const
Provides number of bytes operated upon during an iteration.
Definition: strciphr.h:225
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68