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 10NAMESPACE_BEGIN(CryptoPP) 11 12void SEAL_TestInstantiations() 13{ 14 SEAL<>::Encryption x; 15} 16 17struct 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 32word32 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 45template <class B> 46void SEAL_Policy<B>::CipherSetKey(const NameValuePairs ¶ms, 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 68template <class B> 69void 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 77template <class B> 78void 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 84template <class B> 85void 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 210template class SEAL_Policy<BigEndian>; 211template class SEAL_Policy<LittleEndian>; 212 213NAMESPACE_END 214