00001
00002
00003
00004 #include "pch.h"
00005 #include "seal.h"
00006 #include "sha.h"
00007
00008 NAMESPACE_BEGIN(CryptoPP)
00009
00010 ANONYMOUS_NAMESPACE_BEGIN
00011 struct Gamma
00012 {
00013 Gamma(const byte *key);
00014 word32 Apply(word32 i);
00015
00016 SecBlock<word32> H, Z, D;
00017 word32 lastIndex;
00018 };
00019
00020 Gamma::Gamma(const byte *key)
00021 : lastIndex(0xffffffff), H(5), Z(5), D(16)
00022 {
00023 GetUserKeyBigEndian(H.ptr, 5, key, 20);
00024 memset(D, 0, 64);
00025 }
00026
00027 word32 Gamma::Apply(word32 i)
00028 {
00029 word32 shaIndex = i/5;
00030 if (shaIndex != lastIndex)
00031 {
00032 memcpy(Z, H, 20);
00033 D[0] = shaIndex;
00034 SHA::Transform(Z, D);
00035 lastIndex = shaIndex;
00036 }
00037 return Z[i%5];
00038 }
00039 NAMESPACE_END
00040
00041 SEAL::SEAL(const byte *key, word32 counter, unsigned int L)
00042 : L(L), R(4*L/8192), S(256), T(512),
00043 startCount(counter), counter(counter), position(0), buffer(L/8)
00044 {
00045 assert(L%8192 == 0);
00046
00047 Gamma gamma(key);
00048 unsigned int i;
00049
00050 for (i=0; i<512; i++)
00051 T[i] = gamma.Apply(i);
00052
00053 for (i=0; i<256; i++)
00054 S[i] = gamma.Apply(0x1000+i);
00055
00056 for (i=0; i<4*(L/8192); i++)
00057 R[i] = gamma.Apply(0x2000+i);
00058
00059 Generate(counter, buffer);
00060 }
00061
00062 byte SEAL::GenerateByte()
00063 {
00064 if (position == L/8)
00065 IncrementCounter();
00066 return buffer[position++];
00067 }
00068
00069 void SEAL::ProcessString(byte *outString, const byte *inString, unsigned int length)
00070 {
00071 while (length >= L/8-position)
00072 {
00073 xorbuf(outString, inString, buffer+position, L/8-position);
00074 length -= L/8-position;
00075 inString += L/8-position;
00076 outString += L/8-position;
00077 IncrementCounter();
00078 }
00079
00080 xorbuf(outString, inString, buffer+position, length);
00081 position += length;
00082 }
00083
00084 void SEAL::Seek(unsigned long seekPosition)
00085 {
00086 counter = startCount + seekPosition/(L/8);
00087 position = seekPosition%(L/8);
00088 Generate(counter, buffer);
00089 }
00090
00091 void SEAL::IncrementCounter()
00092 {
00093 counter++;
00094 position = 0;
00095 Generate(counter, buffer);
00096 }
00097
00098 void SEAL::Generate(word32 in, byte *out) const
00099 {
00100 word32 a, b, c, d, n1, n2, n3, n4;
00101 unsigned int p, q;
00102 word32 *wout = (word32 *)out;
00103
00104 for (unsigned int l=0; l<L/8192; l++)
00105 {
00106 a = in ^ R[4*l];
00107 b = rotrFixed(in, 8U) ^ R[4*l+1];
00108 c = rotrFixed(in, 16U) ^ R[4*l+2];
00109 d = rotrFixed(in, 24U) ^ R[4*l+3];
00110
00111 #define Ttab(x) *(word32 *)((byte *)T.ptr+x)
00112
00113 for (unsigned int j=0; j<2; j++)
00114 {
00115 p = a & 0x7fc;
00116 b += Ttab(p);
00117 a = rotrFixed(a, 9U);
00118
00119 p = b & 0x7fc;
00120 c += Ttab(p);
00121 b = rotrFixed(b, 9U);
00122
00123 p = c & 0x7fc;
00124 d += Ttab(p);
00125 c = rotrFixed(c, 9U);
00126
00127 p = d & 0x7fc;
00128 a += Ttab(p);
00129 d = rotrFixed(d, 9U);
00130 }
00131
00132 n1 = d; n2 = b; n3 = a; n4 = c;
00133
00134 p = a & 0x7fc;
00135 b += Ttab(p);
00136 a = rotrFixed(a, 9U);
00137
00138 p = b & 0x7fc;
00139 c += Ttab(p);
00140 b = rotrFixed(b, 9U);
00141
00142 p = c & 0x7fc;
00143 d += Ttab(p);
00144 c = rotrFixed(c, 9U);
00145
00146 p = d & 0x7fc;
00147 a += Ttab(p);
00148 d = rotrFixed(d, 9U);
00149
00150
00151 for (unsigned int i=0; i<64; i++)
00152 {
00153 p = a & 0x7fc;
00154 a = rotrFixed(a, 9U);
00155 b += Ttab(p);
00156 b ^= a;
00157
00158 q = b & 0x7fc;
00159 b = rotrFixed(b, 9U);
00160 c ^= Ttab(q);
00161 c += b;
00162
00163 p = (p+c) & 0x7fc;
00164 c = rotrFixed(c, 9U);
00165 d += Ttab(p);
00166 d ^= c;
00167
00168 q = (q+d) & 0x7fc;
00169 d = rotrFixed(d, 9U);
00170 a ^= Ttab(q);
00171 a += d;
00172
00173 p = (p+a) & 0x7fc;
00174 b ^= Ttab(p);
00175 a = rotrFixed(a, 9U);
00176
00177 q = (q+b) & 0x7fc;
00178 c += Ttab(q);
00179 b = rotrFixed(b, 9U);
00180
00181 p = (p+c) & 0x7fc;
00182 d ^= Ttab(p);
00183 c = rotrFixed(c, 9U);
00184
00185 q = (q+d) & 0x7fc;
00186 d = rotrFixed(d, 9U);
00187 a += Ttab(q);
00188
00189 #ifdef IS_LITTLE_ENDIAN
00190 wout[0] = byteReverse(b + S[4*i+0]);
00191 wout[1] = byteReverse(c ^ S[4*i+1]);
00192 wout[2] = byteReverse(d + S[4*i+2]);
00193 wout[3] = byteReverse(a ^ S[4*i+3]);
00194 #else
00195 wout[0] = b + S[4*i+0];
00196 wout[1] = c ^ S[4*i+1];
00197 wout[2] = d + S[4*i+2];
00198 wout[3] = a ^ S[4*i+3];
00199 #endif
00200 wout += 4;
00201
00202 if (i & 1)
00203 {
00204 a += n3;
00205 b += n4;
00206 c ^= n3;
00207 d ^= n4;
00208 }
00209 else
00210 {
00211 a += n1;
00212 b += n2;
00213 c ^= n1;
00214 d ^= n2;
00215 }
00216 }
00217 }
00218
00219 a = b = c = d = n1 = n2 = n3 = n4 = 0;
00220 p = q = 0;
00221 }
00222
00223 NAMESPACE_END