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