Security Scol plugin
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
15ANONYMOUS_NAMESPACE_BEGIN
16
17using CryptoPP::word32;
18using CryptoPP::word64;
19using CryptoPP::rotlConstant;
20
21word32 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
45word32 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
82ANONYMOUS_NAMESPACE_END
83
84NAMESPACE_BEGIN(CryptoPP)
85
86void 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
132void 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
157void 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
203void 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
234void 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
259NAMESPACE_END
Access a block of memory.
Definition misc.h:2766
Interface for retrieving values given their names.
Definition cryptlib.h:322
Rabbit stream cipher implementation.
Definition rabbit.h:44
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
Operates the keystream.
Definition rabbit.cpp:132
void CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
Key the cipher.
Definition rabbit.cpp:157
void OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
Operates the keystream.
Definition rabbit.cpp:234
void CipherResynchronize(byte *keystreamBuffer, const byte *iv, size_t length)
Resynchronize the cipher.
Definition rabbit.cpp:203
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:62
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition cryptlib.h:145
Utility functions for the Crypto++ library.
void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock=NULLPTR)
Access a block of memory.
Definition misc.h:2739
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:2291
#define EnumToInt(v)
Integer value.
Definition misc.h:502
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