00001
00002
00003
00004 #include "pch.h"
00005
00006 #include "seal.h"
00007 #include "sha.h"
00008 #include "misc.h"
00009
00010 NAMESPACE_BEGIN(CryptoPP)
00011
00012 void SEAL_TestInstantiations()
00013 {
00014 SEAL<>::Encryption x;
00015 }
00016
00017 struct SEAL_Gamma
00018 {
00019 SEAL_Gamma(const byte *key)
00020 : H(5), Z(5), D(16), lastIndex(0xffffffff)
00021 {
00022 GetUserKey(BIG_ENDIAN_ORDER, H.begin(), 5, key, 20);
00023 memset(D, 0, 64);
00024 }
00025
00026 word32 Apply(word32 i);
00027
00028 SecBlock<word32> H, Z, D;
00029 word32 lastIndex;
00030 };
00031
00032 word32 SEAL_Gamma::Apply(word32 i)
00033 {
00034 word32 shaIndex = i/5;
00035 if (shaIndex != lastIndex)
00036 {
00037 memcpy(Z, H, 20);
00038 D[0] = shaIndex;
00039 SHA::Transform(Z, D);
00040 lastIndex = shaIndex;
00041 }
00042 return Z[i%5];
00043 }
00044
00045 template <class B>
00046 void SEAL_Policy<B>::CipherSetKey(const NameValuePairs ¶ms, const byte *key, size_t length)
00047 {
00048 m_insideCounter = m_outsideCounter = m_startCount = 0;
00049
00050 unsigned int L = params.GetIntValueWithDefault("NumberOfOutputBitsPerPositionIndex", 32*1024);
00051 m_iterationsPerCount = L / 8192;
00052
00053 SEAL_Gamma gamma(key);
00054 unsigned int i;
00055
00056 for (i=0; i<512; i++)
00057 m_T[i] = gamma.Apply(i);
00058
00059 for (i=0; i<256; i++)
00060 m_S[i] = gamma.Apply(0x1000+i);
00061
00062 m_R.New(4*(L/8192));
00063
00064 for (i=0; i<m_R.size(); i++)
00065 m_R[i] = gamma.Apply(0x2000+i);
00066 }
00067
00068 template <class B>
00069 void SEAL_Policy<B>::CipherResynchronize(byte *keystreamBuffer, const byte *IV, size_t length)
00070 {
00071 assert(length==4);
00072 m_outsideCounter = IV ? GetWord<word32>(false, BIG_ENDIAN_ORDER, IV) : 0;
00073 m_startCount = m_outsideCounter;
00074 m_insideCounter = 0;
00075 }
00076
00077 template <class B>
00078 void SEAL_Policy<B>::SeekToIteration(lword iterationCount)
00079 {
00080 m_outsideCounter = m_startCount + (unsigned int)(iterationCount / m_iterationsPerCount);
00081 m_insideCounter = (unsigned int)(iterationCount % m_iterationsPerCount);
00082 }
00083
00084 template <class B>
00085 void SEAL_Policy<B>::OperateKeystream(KeystreamOperation operation, byte *output, const byte *input, size_t iterationCount)
00086 {
00087 word32 a, b, c, d, n1, n2, n3, n4;
00088 unsigned int p, q;
00089
00090 for (size_t iteration = 0; iteration < iterationCount; ++iteration)
00091 {
00092 #define Ttab(x) *(word32 *)((byte *)m_T.begin()+x)
00093
00094 a = m_outsideCounter ^ m_R[4*m_insideCounter];
00095 b = rotrFixed(m_outsideCounter, 8U) ^ m_R[4*m_insideCounter+1];
00096 c = rotrFixed(m_outsideCounter, 16U) ^ m_R[4*m_insideCounter+2];
00097 d = rotrFixed(m_outsideCounter, 24U) ^ m_R[4*m_insideCounter+3];
00098
00099 for (unsigned int j=0; j<2; j++)
00100 {
00101 p = a & 0x7fc;
00102 b += Ttab(p);
00103 a = rotrFixed(a, 9U);
00104
00105 p = b & 0x7fc;
00106 c += Ttab(p);
00107 b = rotrFixed(b, 9U);
00108
00109 p = c & 0x7fc;
00110 d += Ttab(p);
00111 c = rotrFixed(c, 9U);
00112
00113 p = d & 0x7fc;
00114 a += Ttab(p);
00115 d = rotrFixed(d, 9U);
00116 }
00117
00118 n1 = d, n2 = b, n3 = a, n4 = c;
00119
00120 p = a & 0x7fc;
00121 b += Ttab(p);
00122 a = rotrFixed(a, 9U);
00123
00124 p = b & 0x7fc;
00125 c += Ttab(p);
00126 b = rotrFixed(b, 9U);
00127
00128 p = c & 0x7fc;
00129 d += Ttab(p);
00130 c = rotrFixed(c, 9U);
00131
00132 p = d & 0x7fc;
00133 a += Ttab(p);
00134 d = rotrFixed(d, 9U);
00135
00136
00137 for (unsigned int i=0; i<64; i++)
00138 {
00139 p = a & 0x7fc;
00140 a = rotrFixed(a, 9U);
00141 b += Ttab(p);
00142 b ^= a;
00143
00144 q = b & 0x7fc;
00145 b = rotrFixed(b, 9U);
00146 c ^= Ttab(q);
00147 c += b;
00148
00149 p = (p+c) & 0x7fc;
00150 c = rotrFixed(c, 9U);
00151 d += Ttab(p);
00152 d ^= c;
00153
00154 q = (q+d) & 0x7fc;
00155 d = rotrFixed(d, 9U);
00156 a ^= Ttab(q);
00157 a += d;
00158
00159 p = (p+a) & 0x7fc;
00160 b ^= Ttab(p);
00161 a = rotrFixed(a, 9U);
00162
00163 q = (q+b) & 0x7fc;
00164 c += Ttab(q);
00165 b = rotrFixed(b, 9U);
00166
00167 p = (p+c) & 0x7fc;
00168 d ^= Ttab(p);
00169 c = rotrFixed(c, 9U);
00170
00171 q = (q+d) & 0x7fc;
00172 d = rotrFixed(d, 9U);
00173 a += Ttab(q);
00174
00175 #define SEAL_OUTPUT(x) \
00176 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 0, b + m_S[4*i+0]);\
00177 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 1, c ^ m_S[4*i+1]);\
00178 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 2, d + m_S[4*i+2]);\
00179 CRYPTOPP_KEYSTREAM_OUTPUT_WORD(x, B::ToEnum(), 3, a ^ m_S[4*i+3]);
00180
00181 CRYPTOPP_KEYSTREAM_OUTPUT_SWITCH(SEAL_OUTPUT, 4*4);
00182
00183 if (i & 1)
00184 {
00185 a += n3;
00186 b += n4;
00187 c ^= n3;
00188 d ^= n4;
00189 }
00190 else
00191 {
00192 a += n1;
00193 b += n2;
00194 c ^= n1;
00195 d ^= n2;
00196 }
00197 }
00198
00199 if (++m_insideCounter == m_iterationsPerCount)
00200 {
00201 ++m_outsideCounter;
00202 m_insideCounter = 0;
00203 }
00204 }
00205
00206 a = b = c = d = n1 = n2 = n3 = n4 = 0;
00207 p = q = 0;
00208 }
00209
00210 template class SEAL_Policy<BigEndian>;
00211 template class SEAL_Policy<LittleEndian>;
00212
00213 NAMESPACE_END