Crypto++
seal.cpp
1 // seal.cpp - written and placed in the public domain by Wei Dai
2 // updated to SEAL 3.0 by Leonard Janke
3 
4 #include "pch.h"
5 
6 #include "seal.h"
7 #include "sha.h"
8 #include "misc.h"
9 
10 NAMESPACE_BEGIN(CryptoPP)
11 
12 void SEAL_TestInstantiations()
13 {
15 }
16 
17 struct SEAL_Gamma
18 {
19  SEAL_Gamma(const byte *key)
20  : H(5), Z(5), D(16), lastIndex(0xffffffff)
21  {
22  GetUserKey(BIG_ENDIAN_ORDER, H.begin(), 5, key, 20);
23  memset(D, 0, 64);
24  }
25 
26  word32 Apply(word32 i);
27 
28  SecBlock<word32> H, Z, D;
29  word32 lastIndex;
30 };
31 
32 word32 SEAL_Gamma::Apply(word32 i)
33 {
34  word32 shaIndex = i/5;
35  if (shaIndex != lastIndex)
36  {
37  memcpy(Z, H, 20);
38  D[0] = shaIndex;
39  SHA::Transform(Z, D);
40  lastIndex = shaIndex;
41  }
42  return Z[i%5];
43 }
44 
45 template <class B>
46 void SEAL_Policy<B>::CipherSetKey(const NameValuePairs &params, const byte *key, size_t length)
47 {
48  m_insideCounter = m_outsideCounter = m_startCount = 0;
49 
50  unsigned int L = params.GetIntValueWithDefault("NumberOfOutputBitsPerPositionIndex", 32*1024);
51  m_iterationsPerCount = L / 8192;
52 
53  SEAL_Gamma gamma(key);
54  unsigned int i;
55 
56  for (i=0; i<512; i++)
57  m_T[i] = gamma.Apply(i);
58 
59  for (i=0; i<256; i++)
60  m_S[i] = gamma.Apply(0x1000+i);
61 
62  m_R.New(4*(L/8192));
63 
64  for (i=0; i<m_R.size(); i++)
65  m_R[i] = gamma.Apply(0x2000+i);
66 }
67 
68 template <class B>
69 void SEAL_Policy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
70 {
71  assert(length==4);
72  m_outsideCounter = IV ? GetWord<word32>(false, BIG_ENDIAN_ORDER, IV) : 0;
73  m_startCount = m_outsideCounter;
74  m_insideCounter = 0;
75 }
76 
77 template <class B>
78 void SEAL_Policy<B>::SeekToIteration(lword iterationCount)
79 {
80  m_outsideCounter = m_startCount + (unsigned int)(iterationCount / m_iterationsPerCount);
81  m_insideCounter = (unsigned int)(iterationCount % m_iterationsPerCount);
82 }
83 
84 template <class B>
85 void SEAL_Policy<B>::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
86 {
87  word32 a, b, c, d, n1, n2, n3, n4;
88  unsigned int p, q;
89 
90  for (size_t iteration = 0; iteration < iterationCount; ++iteration)
91  {
92 #define Ttab(x) *(word32 *)((byte *)m_T.begin()+x)
93 
94  a = m_outsideCounter ^ m_R[4*m_insideCounter];
95  b = rotrFixed(m_outsideCounter, 8U) ^ m_R[4*m_insideCounter+1];
96  c = rotrFixed(m_outsideCounter, 16U) ^ m_R[4*m_insideCounter+2];
97  d = rotrFixed(m_outsideCounter, 24U) ^ m_R[4*m_insideCounter+3];
98 
99  for (unsigned int j=0; j<2; j++)
100  {
101  p = a & 0x7fc;
102  b += Ttab(p);
103  a = rotrFixed(a, 9U);
104 
105  p = b & 0x7fc;
106  c += Ttab(p);
107  b = rotrFixed(b, 9U);
108 
109  p = c & 0x7fc;
110  d += Ttab(p);
111  c = rotrFixed(c, 9U);
112 
113  p = d & 0x7fc;
114  a += Ttab(p);
115  d = rotrFixed(d, 9U);
116  }
117 
118  n1 = d, n2 = b, n3 = a, n4 = c;
119 
120  p = a & 0x7fc;
121  b += Ttab(p);
122  a = rotrFixed(a, 9U);
123 
124  p = b & 0x7fc;
125  c += Ttab(p);
126  b = rotrFixed(b, 9U);
127 
128  p = c & 0x7fc;
129  d += Ttab(p);
130  c = rotrFixed(c, 9U);
131 
132  p = d & 0x7fc;
133  a += Ttab(p);
134  d = rotrFixed(d, 9U);
135 
136  // generate 8192 bits
137  for (unsigned int i=0; i<64; i++)
138  {
139  p = a & 0x7fc;
140  a = rotrFixed(a, 9U);
141  b += Ttab(p);
142  b ^= a;
143 
144  q = b & 0x7fc;
145  b = rotrFixed(b, 9U);
146  c ^= Ttab(q);
147  c += b;
148 
149  p = (p+c) & 0x7fc;
150  c = rotrFixed(c, 9U);
151  d += Ttab(p);
152  d ^= c;
153 
154  q = (q+d) & 0x7fc;
155  d = rotrFixed(d, 9U);
156  a ^= Ttab(q);
157  a += d;
158 
159  p = (p+a) & 0x7fc;
160  b ^= Ttab(p);
161  a = rotrFixed(a, 9U);
162 
163  q = (q+b) & 0x7fc;
164  c += Ttab(q);
165  b = rotrFixed(b, 9U);
166 
167  p = (p+c) & 0x7fc;
168  d ^= Ttab(p);
169  c = rotrFixed(c, 9U);
170 
171  q = (q+d) & 0x7fc;
172  d = rotrFixed(d, 9U);
173  a += Ttab(q);
174 
175 #define SEAL_OUTPUT(x) \
176  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, b + m_S[4*i+0]);\
177  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 1, c ^ m_S[4*i+1]);\
178  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 2, d + m_S[4*i+2]);\
179  CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 3, a ^ m_S[4*i+3]);
180 
181  CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SEAL_OUTPUT, 4*4);
182 
183  if (i & 1)
184  {
185  a += n3;
186  b += n4;
187  c ^= n3;
188  d ^= n4;
189  }
190  else
191  {
192  a += n1;
193  b += n2;
194  c ^= n1;
195  d ^= n2;
196  }
197  }
198 
199  if (++m_insideCounter == m_iterationsPerCount)
200  {
201  ++m_outsideCounter;
202  m_insideCounter = 0;
203  }
204  }
205 
206  a = b = c = d = n1 = n2 = n3 = n4 = 0;
207  p = q = 0;
208 }
209 
210 template class SEAL_Policy<BigEndian>;
211 template class SEAL_Policy<LittleEndian>;
212 
213 NAMESPACE_END
int GetIntValueWithDefault(const char *name, int defaultValue) const
get a named value with type int, with default
Definition: cryptlib.h:286
interface for retrieving values given their names
Definition: cryptlib.h:225