00001
00002
00003 #include "pch.h"
00004 #include "ida.h"
00005
00006 #include "algebra.h"
00007 #include "gf2_32.h"
00008 #include "polynomi.h"
00009
00010 #include "polynomi.cpp"
00011
00012 ANONYMOUS_NAMESPACE_BEGIN
00013 static const CryptoPP::GF2_32 field;
00014 NAMESPACE_END
00015
00016 using namespace std;
00017
00018 NAMESPACE_BEGIN(CryptoPP)
00019
00020 RawIDA::RawIDA(unsigned int threshold, BufferedTransformation *outQueue)
00021 : Filter(outQueue), m_lastMapPosition(m_inputChannelMap.end()), m_threshold(threshold), m_channelsReady(0), m_channelsFinished(0)
00022 , m_w(threshold), m_y(threshold)
00023 {
00024 assert(threshold > 0);
00025 m_inputQueues.reserve(threshold);
00026 }
00027
00028 unsigned int RawIDA::InsertInputChannel(word32 channelId)
00029 {
00030 if (m_lastMapPosition != m_inputChannelMap.end())
00031 {
00032 if (m_lastMapPosition->first == channelId)
00033 goto skipFind;
00034 ++m_lastMapPosition;
00035 if (m_lastMapPosition != m_inputChannelMap.end() && m_lastMapPosition->first == channelId)
00036 goto skipFind;
00037 }
00038 m_lastMapPosition = m_inputChannelMap.find(channelId);
00039
00040 skipFind:
00041 if (m_lastMapPosition == m_inputChannelMap.end())
00042 {
00043 if (m_inputChannelIds.size() == m_threshold)
00044 return m_threshold;
00045
00046 m_lastMapPosition = m_inputChannelMap.insert(pair<const unsigned long, unsigned int>(channelId, m_inputChannelIds.size())).first;
00047 m_inputQueues.push_back(MessageQueue());
00048 m_inputChannelIds.push_back(channelId);
00049
00050 if (m_inputChannelIds.size() == m_threshold)
00051 PrepareInterpolation();
00052 }
00053 return m_lastMapPosition->second;
00054 }
00055
00056 unsigned int RawIDA::LookupInputChannel(word32 channelId) const
00057 {
00058 map<word32, unsigned int>::const_iterator it = m_inputChannelMap.find(channelId);
00059 if (it == m_inputChannelMap.end())
00060 return m_threshold;
00061 else
00062 return it->second;
00063 }
00064
00065 void RawIDA::ChannelData(word32 channelId, const byte *inString, unsigned int length)
00066 {
00067 unsigned int i = InsertInputChannel(channelId);
00068 if (i < m_threshold)
00069 {
00070 unsigned long size = m_inputQueues[i].MaxRetrievable();
00071 m_inputQueues[i].Put(inString, length);
00072 if (size < 4 && size + length >= 4)
00073 {
00074 m_channelsReady++;
00075 if (m_channelsReady == m_threshold)
00076 ProcessInputQueues();
00077 }
00078 }
00079 }
00080
00081 unsigned int RawIDA::InputBuffered(word32 channelId) const
00082 {
00083 unsigned int i = LookupInputChannel(channelId);
00084 return i < m_threshold ? m_inputQueues[i].MaxRetrievable() : 0;
00085 }
00086
00087 void RawIDA::ChannelMessageEnd(const string &channel, int propagation)
00088 {
00089 unsigned int i = InsertInputChannel(StringToWord<word32>(channel));
00090 if (i < m_threshold)
00091 {
00092 m_inputQueues[i].MessageEnd();
00093 if (m_inputQueues[i].NumberOfMessages() == 1)
00094 {
00095 m_channelsFinished++;
00096 if (m_channelsFinished == m_threshold)
00097 {
00098 m_channelsReady = 0;
00099 for (i=0; i<m_threshold; i++)
00100 m_channelsReady += m_inputQueues[i].AnyRetrievable();
00101 ProcessInputQueues();
00102 }
00103 }
00104 }
00105 }
00106
00107 void RawIDA::ComputeV(unsigned int i)
00108 {
00109 if (i >= m_v.size())
00110 {
00111 m_v.resize(i+1);
00112 m_outputToInput.resize(i+1);
00113 }
00114
00115 m_outputToInput[i] = LookupInputChannel(m_outputChannelIds[i]);
00116 if (m_outputToInput[i] == m_threshold && i * m_threshold <= 1000*1000)
00117 {
00118 m_v[i].Resize(m_threshold);
00119 PrepareBulkPolynomialInterpolationAt(field, m_v[i].ptr, m_outputChannelIds[i], m_inputChannelIds.begin(), m_w.ptr, m_threshold);
00120 }
00121 }
00122
00123 void RawIDA::AddOutputChannel(word32 channelId)
00124 {
00125 m_outputChannelIds.push_back(channelId);
00126 m_outputQueues.push_back(ByteQueue());
00127 m_channelSwitches.push_back(ChannelSwitch(*AttachedTransformation(), WordToString(channelId)));
00128 if (m_inputChannelIds.size() == m_threshold)
00129 ComputeV(m_outputChannelIds.size() - 1);
00130 }
00131
00132 void RawIDA::PrepareInterpolation()
00133 {
00134 assert(m_inputChannelIds.size() == m_threshold);
00135 PrepareBulkPolynomialInterpolation(field, m_w.ptr, m_inputChannelIds.begin(), m_threshold);
00136
00137 for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00138 ComputeV(i);
00139 }
00140
00141 void RawIDA::ProcessInputQueues()
00142 {
00143 bool finished = (m_channelsFinished == m_threshold);
00144 unsigned int i;
00145
00146 while (finished ? m_channelsReady > 0 : m_channelsReady == m_threshold)
00147 {
00148 m_channelsReady = 0;
00149 for (i=0; i<m_threshold; i++)
00150 {
00151 MessageQueue &queue = m_inputQueues[i];
00152 queue.GetWord32(m_y[i]);
00153
00154 if (finished)
00155 m_channelsReady += queue.AnyRetrievable();
00156 else
00157 m_channelsReady += queue.NumberOfMessages() > 0 || queue.MaxRetrievable() >= 4;
00158 }
00159
00160 for (i=0; i<m_outputChannelIds.size(); i++)
00161 {
00162 if (m_outputToInput[i] != m_threshold)
00163 m_outputQueues[i].PutWord32(m_y[m_outputToInput[i]]);
00164 else if (m_v[i].size == m_threshold)
00165 m_outputQueues[i].PutWord32(BulkPolynomialInterpolateAt(field, m_y.ptr, m_v[i].ptr, m_threshold));
00166 else
00167 {
00168 m_u.Resize(m_threshold);
00169 PrepareBulkPolynomialInterpolationAt(field, m_u.ptr, m_outputChannelIds[i], m_inputChannelIds.begin(), m_w.ptr, m_threshold);
00170 m_outputQueues[i].PutWord32(BulkPolynomialInterpolateAt(field, m_y.ptr, m_u.ptr, m_threshold));
00171 }
00172 }
00173 }
00174
00175 if (m_outputChannelIds.size() > 0 && m_outputQueues[0].AnyRetrievable())
00176 FlushOutputQueues();
00177
00178 if (finished)
00179 {
00180 OutputMessageEnds();
00181
00182 m_channelsReady = 0;
00183 m_channelsFinished = 0;
00184 m_v.clear();
00185
00186 vector<MessageQueue> inputQueues;
00187 vector<word32> inputChannelIds;
00188
00189 inputQueues.swap(m_inputQueues);
00190 inputChannelIds.swap(m_inputChannelIds);
00191 m_inputChannelMap.clear();
00192 m_lastMapPosition = m_inputChannelMap.end();
00193
00194 for (i=0; i<m_threshold; i++)
00195 {
00196 inputQueues[i].RetrieveNextMessage();
00197 ChannelSwitch channelSwitch(*this, WordToString(inputChannelIds[i]));
00198 inputQueues[i].TransferAllTo(channelSwitch);
00199 }
00200 }
00201 }
00202
00203 void RawIDA::FlushOutputQueues()
00204 {
00205 for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00206 m_outputQueues[i].TransferTo(m_channelSwitches[i]);
00207 }
00208
00209 void RawIDA::OutputMessageEnds()
00210 {
00211 if (GetAutoSignalPropagation() != 0)
00212 {
00213 for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00214 m_channelSwitches[i].MessageEnd(GetAutoSignalPropagation()-1);
00215 }
00216 }
00217
00218
00219
00220 SecretSharing::SecretSharing(RandomNumberGenerator &rng, unsigned int threshold, unsigned int nShares, BufferedTransformation *outQueue, bool addPadding)
00221 : Filter(outQueue), m_rng(rng), m_ida(threshold, new OutputProxy(*this, true)), m_pad(addPadding)
00222 {
00223 for (unsigned int i=0; i<nShares; i++)
00224 m_ida.AddOutputChannel(i);
00225 }
00226
00227 void SecretSharing::Put(const byte *inString, unsigned int length)
00228 {
00229 SecByteBlock buf(STDMIN(length, 256U));
00230 unsigned int threshold = m_ida.GetThreshold();
00231 while (length > 0)
00232 {
00233 unsigned int len = STDMIN(length, buf.size);
00234 m_ida.ChannelData(0xffffffff, inString, len);
00235 for (unsigned int i=0; i<threshold-1; i++)
00236 {
00237 m_rng.GenerateBlock(buf, len);
00238 m_ida.ChannelData(i, buf, len);
00239 }
00240 length -= len;
00241 inString += len;
00242 }
00243 }
00244
00245 void SecretSharing::MessageEnd(int propagation)
00246 {
00247 m_ida.SetAutoSignalPropagation(propagation);
00248 if (m_pad)
00249 {
00250 SecretSharing::Put(1);
00251 while (m_ida.InputBuffered(0xffffffff) > 0)
00252 SecretSharing::Put(0);
00253 }
00254 m_ida.ChannelMessageEnd(WordToString<word32>(0xffffffff));
00255 for (unsigned int i=0; i<m_ida.GetThreshold()-1; i++)
00256 m_ida.ChannelMessageEnd(WordToString<word32>(i));
00257 }
00258
00259 SecretRecovery::SecretRecovery(unsigned int threshold, BufferedTransformation *outQueue, bool removePadding)
00260 : RawIDA(threshold, outQueue), m_pad(removePadding)
00261 {
00262 AddOutputChannel(0xffffffff);
00263 }
00264
00265 void SecretRecovery::FlushOutputQueues()
00266 {
00267 if (m_pad)
00268 m_outputQueues[0].TransferTo(*AttachedTransformation(), m_outputQueues[0].MaxRetrievable()-4);
00269 else
00270 m_outputQueues[0].TransferTo(*AttachedTransformation());
00271 }
00272
00273 void SecretRecovery::OutputMessageEnds()
00274 {
00275 if (m_pad)
00276 {
00277 PaddingRemover paddingRemover(new Redirector(*AttachedTransformation()));
00278 m_outputQueues[0].TransferAllTo(paddingRemover);
00279 }
00280
00281 if (GetAutoSignalPropagation() != 0)
00282 AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1);
00283 }
00284
00285
00286
00287 InformationDispersal::InformationDispersal(unsigned int threshold, unsigned int nShares, BufferedTransformation *outQueue, bool addPadding)
00288 : Filter(outQueue), m_ida(threshold, new OutputProxy(*this, true)), m_pad(addPadding), m_nextChannel(0)
00289 {
00290 for (unsigned int i=0; i<nShares; i++)
00291 m_ida.AddOutputChannel(i);
00292 }
00293
00294 void InformationDispersal::Put(const byte *inString, unsigned int length)
00295 {
00296 while (length--)
00297 {
00298 m_ida.ChannelData(m_nextChannel, inString, 1);
00299 inString++;
00300 m_nextChannel++;
00301 if (m_nextChannel == m_ida.GetThreshold())
00302 m_nextChannel = 0;
00303 }
00304 }
00305
00306 void InformationDispersal::MessageEnd(int propagation)
00307 {
00308 m_ida.SetAutoSignalPropagation(propagation);
00309 if (m_pad)
00310 InformationDispersal::Put(1);
00311 for (unsigned int i=0; i<m_ida.GetThreshold(); i++)
00312 m_ida.ChannelMessageEnd(WordToString<word32>(i));
00313 }
00314
00315 InformationRecovery::InformationRecovery(unsigned int threshold, BufferedTransformation *outQueue, bool removePadding)
00316 : RawIDA(threshold, outQueue), m_pad(removePadding)
00317 {
00318 for (unsigned int i=0; i<threshold; i++)
00319 AddOutputChannel(i);
00320 }
00321
00322 void InformationRecovery::FlushOutputQueues()
00323 {
00324 while (m_outputQueues[0].AnyRetrievable())
00325 {
00326 for (unsigned int i=0; i<m_outputChannelIds.size(); i++)
00327 m_outputQueues[i].TransferTo(m_queue, 1);
00328 }
00329
00330 if (m_pad)
00331 m_queue.TransferTo(*AttachedTransformation(), m_queue.MaxRetrievable()-4*m_threshold);
00332 else
00333 m_queue.TransferTo(*AttachedTransformation());
00334 }
00335
00336 void InformationRecovery::OutputMessageEnds()
00337 {
00338 if (m_pad)
00339 {
00340 PaddingRemover paddingRemover(new Redirector(*AttachedTransformation()));
00341 m_queue.TransferAllTo(paddingRemover);
00342 }
00343
00344 if (GetAutoSignalPropagation() != 0)
00345 AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1);
00346 }
00347
00348 void PaddingRemover::Put(byte b)
00349 {
00350 if (m_possiblePadding)
00351 {
00352 if (b == 0)
00353 m_zeroCount++;
00354 else
00355 {
00356 AttachedTransformation()->Put(1);
00357 while (m_zeroCount--)
00358 AttachedTransformation()->Put(0);
00359 AttachedTransformation()->Put(b);
00360 m_possiblePadding = false;
00361 }
00362 }
00363 else
00364 {
00365 if (b == 1)
00366 {
00367 m_possiblePadding = true;
00368 m_zeroCount = 0;
00369 }
00370 else
00371 AttachedTransformation()->Put(b);
00372 }
00373 }
00374
00375 void PaddingRemover::Put(const byte *begin, unsigned int length)
00376 {
00377 const byte *const end = begin + length;
00378
00379 if (m_possiblePadding)
00380 {
00381 unsigned int len = find_if(begin, end, bind2nd(not_equal_to<byte>(), 0)) - begin;
00382 m_zeroCount += len;
00383 begin += len;
00384 if (begin == end)
00385 return;
00386 PaddingRemover::Put(*begin++);
00387 }
00388
00389 #if defined(_MSC_VER) && !defined(__MWERKS__)
00390 typedef reverse_iterator<const byte *, const byte> rit;
00391 #else
00392 typedef reverse_iterator<const byte *> rit;
00393 #endif
00394 const byte *x = find_if(rit(end), rit(begin), bind2nd(not_equal_to<byte>(), 0)).base();
00395 if (x != begin && *(x-1) == 1)
00396 {
00397 AttachedTransformation()->Put(begin, x-begin-1);
00398 m_possiblePadding = true;
00399 m_zeroCount = end - x;
00400 }
00401 else
00402 AttachedTransformation()->Put(begin, end-begin);
00403 }
00404
00405 void PaddingRemover::MessageEnd(int propagation)
00406 {
00407 m_possiblePadding = false;
00408 Filter::MessageEnd(propagation);
00409 }
00410
00411 NAMESPACE_END