Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

# fipsalgt.cpp

    00001 // fipsalgt.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 // This file implements the various algorithm tests needed to pass FIPS 140 validation.
    00004 // They're preserved here (commented out) in case Crypto++ needs to be revalidated.
    00005
    00006 #if 0
    00007 #include "dll.h"
    00008
    00009 USING_NAMESPACE(CryptoPP)
    00010 USING_NAMESPACE(std)
    00011
    00012 class LineBreakParser : public AutoSignaling<Bufferless<Filter> >
    00013 {
    00014 public:
    00015         LineBreakParser(BufferedTransformation *attachment=NULL, byte lineEnd='\n')
    00016                 : AutoSignaling<Bufferless<Filter> >(attachment), m_lineEnd(lineEnd) {}
    00017
    00018         unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
    00019         {
    00020                 if (!blocking)
    00021                         throw BlockingInputOnly("LineBreakParser");
    00022
    00023                 unsigned int i, last = 0;
    00024                 for (i=0; i<length; i++)
    00025                 {
    00026                         if (begin[i] == m_lineEnd)
    00027                         {
    00028                                 AttachedTransformation()->Put2(begin+last, i-last, GetAutoSignalPropagation(), blocking);
    00029                                 last = i+1;
    00030                         }
    00031                 }
    00032                 if (last != i)
    00033                         AttachedTransformation()->Put2(begin+last, i-last, 0, blocking);
    00034
    00035                 if (messageEnd && GetAutoSignalPropagation())
    00036                 {
    00037                         AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1, blocking);
    00038                         AttachedTransformation()->MessageSeriesEnd(GetAutoSignalPropagation()-1, blocking);
    00039                 }
    00040
    00041                 return 0;
    00042         }
    00043
    00044 private:
    00045         byte m_lineEnd;
    00046 };
    00047
    00048 class TestDataParser : public Unflushable<FilterWithInputQueue>
    00049 {
    00050 public:
    00051         enum DataType {OTHER, COUNT, KEY_T, IV, INPUT, OUTPUT};
    00052
    00053         TestDataParser(std::string algorithm, std::string test, std::string mode, unsigned int feedbackSize, bool encrypt, BufferedTransformation *attachment)
    00054                 : Unflushable<FilterWithInputQueue>(attachment)
    00055                 , m_algorithm(algorithm), m_test(test), m_mode(mode), m_feedbackSize(feedbackSize)
    00056                 , m_firstLine(true), m_blankLineTransition(0)
    00057         {
    00058                 m_nameToType["COUNT"] = COUNT;
    00059                 m_nameToType["KEY"] = KEY_T;
    00060                 m_nameToType["KEYs"] = KEY_T;
    00061                 m_nameToType["key"] = KEY_T;
    00062                 m_nameToType["IV"] = IV;
    00063                 m_nameToType["IV1"] = IV;
    00064                 m_nameToType["CV"] = IV;
    00065                 m_nameToType["CV1"] = IV;
    00066                 m_nameToType["IB"] = IV;
    00067                 m_nameToType["TEXT"] = INPUT;
    00068                 m_nameToType["RESULT"] = OUTPUT;
    00069                 SetEncrypt(encrypt);
    00070
    00071                 if (m_algorithm == "DSS")
    00072                 {
    00073                         if (m_test == "prime")
    00074                                 m_trigger = "Prime";
    00075                         else if (m_test == "pqg")
    00076                                 m_trigger = "N";
    00077                         else if (m_test == "xy")
    00078                                 m_trigger = "G";
    00079                         else if (m_test == "gensig")
    00080                                 m_trigger = "Msg";
    00081                         else if (m_test == "versig")
    00082                                 m_trigger = "Sig";
    00083                         else if (m_test == "verpqg")
    00084                                 m_trigger = "c";
    00085                 }
    00086         }
    00087
    00088         void SetEncrypt(bool encrypt)
    00089         {
    00090                 m_encrypt = encrypt;
    00091                 if (encrypt)
    00092                 {
    00093                         m_nameToType["PLAINTEXT"] = INPUT;
    00094                         m_nameToType["CIPHERTEXT"] = OUTPUT;
    00095                         m_nameToType["PT"] = INPUT;
    00096                         m_nameToType["CT"] = OUTPUT;
    00097                 }
    00098                 else
    00099                 {
    00100                         m_nameToType["PLAINTEXT"] = OUTPUT;
    00101                         m_nameToType["CIPHERTEXT"] = INPUT;
    00102                         m_nameToType["PT"] = OUTPUT;
    00103                         m_nameToType["CT"] = INPUT;
    00104                 }
    00105
    00106                 if (m_algorithm == "AES")
    00107                 {
    00108                         if (encrypt)
    00109                         {
    00110                                 m_trigger = "PLAINTEXT";
    00111                                 m_typeToName[OUTPUT] = "CIPHERTEXT";
    00112                         }
    00113                         else
    00114                         {
    00115                                 m_trigger = "CIPHERTEXT";
    00116                                 m_typeToName[OUTPUT] = "PLAINTEXT";
    00117                         }
    00118                         m_count = 0;
    00119                 }
    00120         }
    00121
    00122 protected:
    00123         void OutputData(std::string &output, const std::string &key, const std::string &data)
    00124         {
    00125                 output += key;
    00126                 output += "= ";
    00127                 output += data;
    00128                 output += "\n";
    00129         }
    00130
    00131         void OutputData(std::string &output, const std::string &key, int data)
    00132         {
    00133                 OutputData(output, key, IntToString(data));
    00134         }
    00135
    00136         void OutputData(std::string &output, const std::string &key, const SecByteBlock &data)
    00137         {
    00138                 output += key;
    00139                 output += "= ";
    00140                 HexEncoder(new StringSink(output), false).Put(data, data.size());
    00141                 output += "\n";
    00142         }
    00143
    00144         void OutputData(std::string &output, const std::string &key, const Integer &data)
    00145         {
    00146                 SecByteBlock s(data.MinEncodedSize());
    00147                 data.Encode(s, s.size());
    00148                 OutputData(output, key, s);
    00149         }
    00150
    00151         void OutputData(std::string &output, DataType t, const std::string &data)
    00152         {
    00153                 if (m_algorithm == "SKIPJACK")
    00154                 {
    00155                         if (m_test == "KAT")
    00156                         {
    00157                                 if (t == OUTPUT)
    00158                                         output = m_line + data + "\n";
    00159                         }
    00160                         else
    00161                         {
    00162                                 if (t != COUNT)
    00163                                 {
    00164                                         output += m_typeToName[t];
    00165                                         output += "=";
    00166                                 }
    00167                                 output += data;
    00168                                 output += t == OUTPUT ? "\n" : "  ";
    00169                         }
    00170                 }
    00171                 else if (m_algorithm == "TDES" && t == KEY_T && m_typeToName[KEY_T].empty())
    00172                 {
    00173                         output += "KEY1 = ";
    00174                         output += data.substr(0, 16);
    00175                         output += "\nKEY2 = ";
    00176                         output += data.size() > 16 ? data.substr(16, 16) : data.substr(0, 16);
    00177                         output += "\nKEY3 = ";
    00178                         output += data.size() > 32 ? data.substr(32, 16) : data.substr(0, 16);
    00179                         output += "\n";
    00180                 }
    00181                 else
    00182                 {
    00183                         output += m_typeToName[t];
    00184                         output += " = ";
    00185                         output += data;
    00186                         output += "\n";
    00187                 }
    00188         }
    00189
    00190         void OutputData(std::string &output, DataType t, int i)
    00191         {
    00192                 OutputData(output, t, IntToString(i));
    00193         }
    00194
    00195         void OutputData(std::string &output, DataType t, const SecByteBlock &data)
    00196         {
    00197                 std::string hexData;
    00198                 StringSource(data.begin(), data.size(), true, new HexEncoder(new StringSink(hexData), false));
    00199                 OutputData(output, t, hexData);
    00200         }
    00201
    00202         void OutputGivenData(std::string &output, DataType t, bool optional = false)
    00203         {
    00204                 if (m_data.find(m_typeToName[t]) == m_data.end())
    00205                 {
    00206                         if (optional)
    00207                                 return;
    00208                         throw Exception(Exception::OTHER_ERROR, "TestDataParser: key not found: " + m_typeToName[t]);
    00209                 }
    00210
    00211                 OutputData(output, t, m_data[m_typeToName[t]]);
    00212         }
    00213
    00214         template <class T>
    00215                 BlockCipher * NewBT(T *)
    00216         {
    00217                 if (!m_encrypt && (m_mode == "ECB" || m_mode == "CBC"))
    00218                         return new typename T::Decryption;
    00219                 else
    00220                         return new typename T::Encryption;
    00221         }
    00222
    00223         template <class T>
    00224                 SymmetricCipher * NewMode(T *, BlockCipher &bt, const byte *iv)
    00225         {
    00226                 if (!m_encrypt)
    00227                         return new typename T::Decryption(bt, iv, m_feedbackSize/8);
    00228                 else
    00229                         return new typename T::Encryption(bt, iv, m_feedbackSize/8);
    00230         }
    00231
    00232         static inline void Xor(SecByteBlock &z, const SecByteBlock &x, const SecByteBlock &y)
    00233         {
    00234                 assert(x.size() == y.size());
    00235                 z.resize(x.size());
    00236                 xorbuf(z, x, y, x.size());
    00237         }
    00238
    00239         SecByteBlock UpdateKey(SecByteBlock key, const SecByteBlock *text)
    00240         {
    00241                 unsigned int innerCount = (m_algorithm == "AES") ? 1000 : 10000;
    00242                 int keySize = key.size(), blockSize = text[0].size();
    00243                 SecByteBlock x(keySize);
    00244                 for (int k=0; k<keySize;)
    00245                 {
    00246                         int pos = innerCount * blockSize - keySize + k;
    00247                         memcpy(x + k, text[pos / blockSize] + pos % blockSize, blockSize - pos % blockSize);
    00248                         k += blockSize - pos % blockSize;
    00249                 }
    00250
    00251                 if (m_algorithm == "TDES" || m_algorithm == "DES")
    00252                 {
    00253                         for (int i=0; i<keySize; i+=8)
    00254                         {
    00255                                 xorbuf(key+i, x+keySize-8-i, 8);
    00256                                 DES::CorrectKeyParityBits(key+i);
    00257                         }
    00258                 }
    00259                 else
    00260                         xorbuf(key, x, keySize);
    00261
    00262                 return key;
    00263         }
    00264
    00265         static inline void AssignLeftMostBits(SecByteBlock &z, const SecByteBlock &x, unsigned int K)
    00266         {
    00267                 z.Assign(x, K/8);
    00268         }
    00269
    00270         virtual void DoTest()
    00271         {
    00272                 std::string output;
    00273
    00274                 if (m_algorithm == "DSS")
    00275                 {
    00276                         if (m_test == "sha")
    00277                         {
    00278                                 assert(m_compactString.size() >= 2);
    00279                                 assert(m_compactString[0] == m_compactString.size()-2);
    00280                                 bool b = !!m_compactString[1];
    00281                                 Integer m;
    00282                                 unsigned int bitLength = 0;
    00283
    00284                                 for (unsigned int j = 2; j < m_compactString.size(); j++)
    00285                                 {
    00286                                         m <<= m_compactString[j];
    00287                                         for (unsigned int k = 0; k < m_compactString[j]; k++)
    00288                                                 m.SetBit(k, b);
    00289                                         bitLength += m_compactString[j];
    00290                                         b = !b;
    00291                                 }
    00292                                 m_compactString.clear();
    00293                                 assert(bitLength % 8 == 0);
    00294
    00295                                 SecByteBlock message(bitLength / 8);
    00296                                 m.Encode(message, message.size());
    00297                                 SHA sha;
    00298
    00299                                 if (m_bracketString == "SHS Type 3 Strings")
    00300                                 {
    00301                                         SecByteBlock m1;
    00302                                         for (int j = 0; j < 100; j++)
    00303                                         {
    00304                                                 for (word32 i = 1; i <= 50000; i++)
    00305                                                 {
    00306                                                         m1.resize(message.size() + j/4 + 3 + 4);
    00307                                                         memcpy(m1, message, message.size());
    00308                                                         memset(m1 + message.size(), 0, j/4 + 3);
    00309                                                         PutWord(false, BIG_ENDIAN_ORDER, m1 + m1.size() - 4, i);
    00310                                                         message.resize(sha.DigestSize());
    00311                                                         sha.CalculateDigest(message, m1, m1.size());
    00312                                                 }
    00313                                                 StringSource(message, message.size(), true, new HexEncoder(new StringSink(output)));
    00314                                                 output += " ^\n";
    00315                                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00316                                                 output.resize(0);
    00317                                         }
    00318                                 }
    00319                                 else
    00320                                 {
    00321                                         StringSource(message, message.size(), true, new HashFilter(sha, new HexEncoder(new StringSink(output))));
    00322                                         output += " ^\n";
    00323                                         AttachedTransformation()->Put((byte *)output.data(), output.size());
    00324                                 }
    00325                         }
    00326                         else if (m_test == "prime")
    00327                         {
    00328                                 Integer p((m_data["Prime"] + "h").c_str());
    00329                                 OutputData(output, "result", VerifyPrime(m_rng, p, 2) ? "P" : "F");
    00330                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00331                                 output.resize(0);
    00332                         }
    00333                         else if (m_test == "pqg")
    00334                         {
    00335                                 int n = atol(m_data["N"].c_str());
    00336                                 for (int i=0; i<n; i++)
    00337                                 {
    00338                                         Integer p, q, h, g;
    00339                                         int counter;
    00340
    00341                                         SecByteBlock seed(SHA::DIGESTSIZE);
    00342                                         do
    00343                                         {
    00344                                                 m_rng.GenerateBlock(seed, seed.size());
    00345                                         }
    00346                                         while (!DSA::GeneratePrimes(seed, seed.size()*8, counter, p, 1024, q));
    00347                                         h.Randomize(m_rng, 2, p-2);
    00348                                         g = a_exp_b_mod_c(h, (p-1)/q, p);
    00349
    00350                                         OutputData(output, "P", p);
    00351                                         OutputData(output, "Q", q);
    00352                                         OutputData(output, "G", g);
    00353                                         OutputData(output, "Seed", seed);
    00354                                         OutputData(output, "H", h);
    00355                                         OutputData(output, "c", counter);
    00356                                         AttachedTransformation()->Put((byte *)output.data(), output.size());
    00357                                         output.resize(0);
    00358                                 }
    00359                         }
    00360                         else if (m_test == "xy")
    00361                         {
    00362                                 Integer p((m_data["P"] + "h").c_str());
    00363                                 Integer q((m_data["Q"] + "h").c_str());
    00364                                 Integer g((m_data["G"] + "h").c_str());
    00365
    00366                                 for (int i=0; i<10; i++)
    00367                                 {
    00368                                         DSA::Signer priv(m_rng, p, q, g);
    00369                                         DSA::Verifier pub(priv);
    00370
    00371                                         OutputData(output, "X", priv.GetKey().GetPrivateExponent());
    00372                                         OutputData(output, "Y", pub.GetKey().GetPublicElement());
    00373                                         AttachedTransformation()->Put((byte *)output.data(), output.size());
    00374                                         output.resize(0);
    00375                                 }
    00376                         }
    00377                         else if (m_test == "gensig")
    00378                         {
    00379                                 Integer p((m_data["P"] + "h").c_str());
    00380                                 Integer q((m_data["Q"] + "h").c_str());
    00381                                 Integer g((m_data["G"] + "h").c_str());
    00382                                 Integer x((m_data["X"] + "h").c_str());
    00383                                 DSA::Signer signer(p, q, g, x);
    00384
    00385                                 SecByteBlock sig(signer.SignatureLength());
    00386                                 StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size()))));
    00387                                 OutputData(output, "Sig", sig);
    00388                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00389                                 output.resize(0);
    00390                         }
    00391                         else if (m_test == "versig")
    00392                         {
    00393                                 Integer p((m_data["P"] + "h").c_str());
    00394                                 Integer q((m_data["Q"] + "h").c_str());
    00395                                 Integer g((m_data["G"] + "h").c_str());
    00396                                 Integer y((m_data["Y"] + "h").c_str());
    00397                                 DSA::Verifier verifier(p, q, g, y);
    00398
    00399                                 HexDecoder filter(new SignatureVerificationFilter(verifier));
    00400                                 StringSource(m_data["Sig"], true, new Redirector(filter, false));
    00401                                 StringSource(m_data["Msg"], true, new Redirector(filter, false));
    00402                                 filter.MessageEnd();
    00403                                 byte b;
    00404                                 filter.Get(b);
    00405                                 OutputData(output, "result", b ? "P" : "F");
    00406                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00407                                 output.resize(0);
    00408                         }
    00409                         else if (m_test == "verpqg")
    00410                         {
    00411                                 Integer p((m_data["P"] + "h").c_str());
    00412                                 Integer q((m_data["Q"] + "h").c_str());
    00413                                 Integer g((m_data["G"] + "h").c_str());
    00414                                 Integer h((m_data["H"] + "h").c_str());
    00415                                 int c = atol(m_data["c"].c_str());
    00416                                 SecByteBlock seed(m_data["Seed"].size()/2);
    00417                                 StringSource(m_data["Seed"], true, new HexDecoder(new ArraySink(seed, seed.size())));
    00418
    00419                                 Integer p1, q1;
    00420                                 bool result = DSA::GeneratePrimes(seed, seed.size()*8, c, p1, 1024, q1, true);
    00421                                 result = result && (p1 == p && q1 == q);
    00422                                 result = result && g == a_exp_b_mod_c(h, (p-1)/q, p);
    00423
    00424                                 OutputData(output, "result", result ? "P" : "F");
    00425                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00426                                 output.resize(0);
    00427                         }
    00428
    00429                         return;
    00430                 }
    00431
    00432                 SecByteBlock &key = m_data2[KEY_T];
    00433
    00434                 if (m_algorithm == "TDES")
    00435                 {
    00436                         if (!m_data["KEY1"].empty())
    00437                         {
    00438                                 const std::string keys[3] = {m_data["KEY1"], m_data["KEY2"], m_data["KEY3"]};
    00439                                 key.resize(24);
    00440                                 HexDecoder hexDec(new ArraySink(key, key.size()));
    00441                                 for (int i=0; i<3; i++)
    00442                                         hexDec.Put((byte *)keys[i].data(), keys[i].size());
    00443
    00444                                 if (keys[0] == keys[2])
    00445                                 {
    00446                                         if (keys[0] == keys[1])
    00447                                                 key.resize(8);
    00448                                         else
    00449                                                 key.resize(16);
    00450                                 }
    00451                                 else
    00452                                         key.resize(24);
    00453                         }
    00454                 }
    00455
    00456                 member_ptr<BlockCipher> pBT;
    00457                 if (m_algorithm == "DES")
    00458                         pBT.reset(NewBT((DES*)0));
    00459                 else if (m_algorithm == "TDES")
    00460                 {
    00461                         if (key.size() == 8)
    00462                                 pBT.reset(NewBT((DES*)0));
    00463                         else if (key.size() == 16)
    00464                                 pBT.reset(NewBT((DES_EDE2*)0));
    00465                         else
    00466                                 pBT.reset(NewBT((DES_EDE3*)0));
    00467                 }
    00468                 else if (m_algorithm == "SKIPJACK")
    00469                         pBT.reset(NewBT((SKIPJACK*)0));
    00470                 else if (m_algorithm == "AES")
    00471                         pBT.reset(NewBT((AES*)0));
    00472                 else
    00473                         throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected algorithm: " + m_algorithm);
    00474
    00475                 if (!pBT->IsValidKeyLength(key.size()))
    00476                         key.CleanNew(pBT->DefaultKeyLength());  // for Scbcvrct
    00477                 pBT->SetKey(key.data(), key.size());
    00478
    00479                 SecByteBlock &iv = m_data2[IV];
    00480                 if (iv.empty())
    00481                         iv.CleanNew(pBT->BlockSize());
    00482
    00483                 member_ptr<SymmetricCipher> pCipher;
    00484                 unsigned int K = m_feedbackSize;
    00485
    00486                 if (m_mode == "ECB")
    00487                         pCipher.reset(NewMode((ECB_Mode_ExternalCipher*)0, *pBT, iv));
    00488                 else if (m_mode == "CBC")
    00489                         pCipher.reset(NewMode((CBC_Mode_ExternalCipher*)0, *pBT, iv));
    00490                 else if (m_mode == "CFB")
    00491                         pCipher.reset(NewMode((CFB_Mode_ExternalCipher*)0, *pBT, iv));
    00492                 else if (m_mode == "OFB")
    00493                         pCipher.reset(NewMode((OFB_Mode_ExternalCipher*)0, *pBT, iv));
    00494                 else
    00495                         throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode);
    00496
    00497                 bool encrypt = m_encrypt;
    00498
    00499                 if (m_test == "MONTE")
    00500                 {
    00501                         SecByteBlock KEY[401];
    00502                         KEY[0] = key;
    00503                         int keySize = key.size();
    00504                         int blockSize = pBT->BlockSize();
    00505
    00506                         SecByteBlock IB[10001], OB[10001], PT[10001], CT[10001], RESULT[10001], TXT[10001], CV[10001];
    00507                         PT[0] = GetData("PLAINTEXT");
    00508                         CT[0] = GetData("CIPHERTEXT");
    00509                         CV[0] = IB[0] = iv;
    00510                         TXT[0] = GetData("TEXT");
    00511
    00512                         unsigned int outerCount = (m_algorithm == "AES") ? 100 : 400;
    00513                         unsigned int innerCount = (m_algorithm == "AES") ? 1000 : 10000;
    00514
    00515                         for (int i=0; i<outerCount; i++)
    00516                         {
    00517                                 pBT->SetKey(KEY[i], keySize);
    00518
    00519                                 for (int j=0; j<innerCount; j++)
    00520                                 {
    00521                                         if (m_mode == "ECB")
    00522                                         {
    00523                                                 if (encrypt)
    00524                                                 {
    00525                                                         IB[j] = PT[j];
    00526                                                         CT[j].resize(blockSize);
    00527                                                         pBT->ProcessBlock(IB[j], CT[j]);
    00528                                                         PT[j+1] = CT[j];
    00529                                                 }
    00530                                                 else
    00531                                                 {
    00532                                                         IB[j] = CT[j];
    00533                                                         PT[j].resize(blockSize);
    00534                                                         pBT->ProcessBlock(IB[j], PT[j]);
    00535                                                         CT[j+1] = PT[j];
    00536                                                 }
    00537                                         }
    00538                                         else if (m_mode == "OFB")
    00539                                         {
    00540                                                 OB[j].resize(blockSize);
    00541                                                 pBT->ProcessBlock(IB[j], OB[j]);
    00542                                                 Xor(RESULT[j], OB[j], TXT[j]);
    00543                                                 TXT[j+1] = IB[j];
    00544                                                 IB[j+1] = OB[j];
    00545                                         }
    00546                                         else if (m_mode == "CBC")
    00547                                         {
    00548                                                 if (encrypt)
    00549                                                 {
    00550                                                         Xor(IB[j], PT[j], CV[j]);
    00551                                                         CT[j].resize(blockSize);
    00552                                                         pBT->ProcessBlock(IB[j], CT[j]);
    00553                                                         PT[j+1] = CV[j];
    00554                                                         CV[j+1] = CT[j];
    00555                                                 }
    00556                                                 else
    00557                                                 {
    00558                                                         IB[j] = CT[j];
    00559                                                         OB[j].resize(blockSize);
    00560                                                         pBT->ProcessBlock(IB[j], OB[j]);
    00561                                                         Xor(PT[j], OB[j], CV[j]);
    00562                                                         CV[j+1] = CT[j];
    00563                                                         CT[j+1] = PT[j];
    00564                                                 }
    00565                                         }
    00566                                         else if (m_mode == "CFB")
    00567                                         {
    00568                                                 if (encrypt)
    00569                                                 {
    00570                                                         OB[j].resize(blockSize);
    00571                                                         pBT->ProcessBlock(IB[j], OB[j]);
    00572                                                         AssignLeftMostBits(CT[j], OB[j], K);
    00573                                                         Xor(CT[j], CT[j], PT[j]);
    00574                                                         AssignLeftMostBits(PT[j+1], IB[j], K);
    00575                                                         IB[j+1].resize(blockSize);
    00576                                                         memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8);
    00577                                                         memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8);
    00578                                                 }
    00579                                                 else
    00580                                                 {
    00581                                                         OB[j].resize(blockSize);
    00582                                                         pBT->ProcessBlock(IB[j], OB[j]);
    00583                                                         AssignLeftMostBits(PT[j], OB[j], K);
    00584                                                         Xor(PT[j], PT[j], CT[j]);
    00585                                                         IB[j+1].resize(blockSize);
    00586                                                         memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8);
    00587                                                         memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8);
    00588                                                         AssignLeftMostBits(CT[j+1], OB[j], K);
    00589                                                 }
    00590                                         }
    00591                                         else
    00592                                                 throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode);
    00593                                 }
    00594
    00595                                 OutputData(output, COUNT, i);
    00596                                 OutputData(output, KEY_T, KEY[i]);
    00597                                 if (m_mode == "CBC")
    00598                                         OutputData(output, IV, CV[0]);
    00599                                 if (m_mode == "OFB" || m_mode == "CFB")
    00600                                         OutputData(output, IV, IB[0]);
    00601                                 if (m_mode == "ECB" || m_mode == "CBC" || m_mode == "CFB")
    00602                                 {
    00603                                         if (encrypt)
    00604                                         {
    00605                                                 OutputData(output, INPUT, PT[0]);
    00606                                                 OutputData(output, OUTPUT, CT[innerCount-1]);
    00607                                                 KEY[i+1] = UpdateKey(KEY[i], CT);
    00608                                         }
    00609                                         else
    00610                                         {
    00611                                                 OutputData(output, INPUT, CT[0]);
    00612                                                 OutputData(output, OUTPUT, PT[innerCount-1]);
    00613                                                 KEY[i+1] = UpdateKey(KEY[i], PT);
    00614                                         }
    00615                                         PT[0] = PT[innerCount];
    00616                                         IB[0] = IB[innerCount];
    00617                                         CV[0] = CV[innerCount];
    00618                                         CT[0] = CT[innerCount];
    00619                                 }
    00620                                 else if (m_mode == "OFB")
    00621                                 {
    00622                                         OutputData(output, INPUT, TXT[0]);
    00623                                         OutputData(output, OUTPUT, RESULT[innerCount-1]);
    00624                                         KEY[i+1] = UpdateKey(KEY[i], RESULT);
    00625                                         Xor(TXT[0], TXT[0], IB[innerCount-1]);
    00626                                         IB[0] = OB[innerCount-1];
    00627                                 }
    00628                                 output += "\n";
    00629                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00630                                 output.resize(0);
    00631                         }
    00632                 }
    00633                 else if (m_test == "MCT")
    00634                 {
    00635                         SecByteBlock KEY[101];
    00636                         KEY[0] = key;
    00637                         int keySize = key.size();
    00638                         int blockSize = pBT->BlockSize();
    00639
    00640                         SecByteBlock ivs[101], inputs[1001], outputs[1001];
    00641                         ivs[0] = iv;
    00642                         inputs[0] = m_data2[INPUT];
    00643
    00644                         for (int i=0; i<100; i++)
    00645                         {
    00646                                 pCipher->SetKey(KEY[i], keySize, MakeParameters(Name::IV(), (const byte *)ivs[i])(Name::FeedbackSize(), (int)K/8));
    00647
    00648                                 for (int j=0; j<1000; j++)
    00649                                 {
    00650                                         outputs[j] = inputs[j];
    00651                                         pCipher->ProcessString(outputs[j], outputs[j].size());
    00652                                         if (K==8 && m_mode == "CFB")
    00653                                         {
    00654                                                 if (j<16)
    00655                                                         inputs[j+1].Assign(ivs[i]+j, 1);
    00656                                                 else
    00657                                                         inputs[j+1] = outputs[j-16];
    00658                                         }
    00659                                         else if (m_mode == "ECB")
    00660                                                 inputs[j+1] = outputs[j];
    00661                                         else if (j == 0)
    00662                                                 inputs[j+1] = ivs[i];
    00663                                         else
    00664                                                 inputs[j+1] = outputs[j-1];
    00665                                 }
    00666
    00667                                 if (m_algorithm == "AES")
    00668                                         OutputData(output, COUNT, m_count++);
    00669                                 OutputData(output, KEY_T, KEY[i]);
    00670                                 if (m_mode != "ECB")
    00671                                         OutputData(output, IV, ivs[i]);
    00672                                 OutputData(output, INPUT, inputs[0]);
    00673                                 OutputData(output, OUTPUT, outputs[999]);
    00674                                 output += "\n";
    00675                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00676                                 output.resize(0);
    00677
    00678                                 KEY[i+1] = UpdateKey(KEY[i], outputs);
    00679                                 ivs[i+1].CleanNew(pCipher->IVSize());
    00680                                 ivs[i+1] = UpdateKey(ivs[i+1], outputs);
    00681                                 if (K==8 && m_mode == "CFB")
    00682                                         inputs[0] = outputs[999-16];
    00683                                 else if (m_mode == "ECB")
    00684                                         inputs[0] = outputs[999];
    00685                                 else
    00686                                         inputs[0] = outputs[998];
    00687                         }
    00688                 }
    00689                 else
    00690                 {
    00691                         assert(m_test == "KAT");
    00692
    00693                         SecByteBlock &input = m_data2[INPUT];
    00694                         SecByteBlock result(input.size());
    00695                         member_ptr<Filter> pFilter(new StreamTransformationFilter(*pCipher, new ArraySink(result, result.size()), StreamTransformationFilter::NO_PADDING));
    00696                         StringSource(input.data(), input.size(), true, pFilter.release());
    00697
    00698                         OutputGivenData(output, COUNT, true);
    00699                         OutputData(output, KEY_T, key);
    00700                         OutputGivenData(output, IV, true);
    00701                         OutputGivenData(output, INPUT);
    00702                         OutputData(output, OUTPUT, result);
    00703                         output += "\n";
    00704                         AttachedTransformation()->Put((byte *)output.data(), output.size());
    00705                 }
    00706         }
    00707
    00708         std::vector<std::string> Tokenize(const std::string &line)
    00709         {
    00710                 std::vector<std::string> result;
    00711                 std::string s;
    00712                 for (int i=0; i<line.size(); i++)
    00713                 {
    00714                         if (isalnum(line[i]) || line[i] == '^')
    00715                                 s += line[i];
    00716                         else if (!s.empty())
    00717                         {
    00718                                 result.push_back(s);
    00719                                 s = "";
    00720                         }
    00721                         if (line[i] == '=')
    00722                                 result.push_back("=");
    00723                 }
    00724                 result.push_back(s);
    00725                 return result;
    00726         }
    00727
    00728         bool IsolatedMessageEnd(bool blocking)
    00729         {
    00730                 if (!blocking)
    00731                         throw BlockingInputOnly("TestDataParser");
    00732
    00733                 m_line.resize(0);
    00734                 m_inQueue.TransferTo(StringSink(m_line).Ref());
    00735
    00736                 if (m_line[0] == '#')
    00737                         return false;
    00738
    00739                 bool copyLine = false;
    00740
    00741                 if (m_line[0] == '[')
    00742                 {
    00743                         m_bracketString = m_line.substr(1, m_line.size()-2);
    00744                         if (m_bracketString == "ENCRYPT")
    00745                                 SetEncrypt(true);
    00746                         if (m_bracketString == "DECRYPT")
    00747                                 SetEncrypt(false);
    00748                         copyLine = true;
    00749                 }
    00750
    00751                 if (m_line.substr(0, 2) == "H>")
    00752                 {
    00753                         assert(m_test == "sha");
    00754                         m_bracketString = m_line.substr(2, m_line.size()-4);
    00755                         m_line = m_line.substr(0, 13) + "Hashes<H";
    00756                         copyLine = true;
    00757                 }
    00758
    00759                 if (m_line == "D>")
    00760                         copyLine = true;
    00761
    00762                 if (m_line == "<D")
    00763                 {
    00764                         m_line += "\n";
    00765                         copyLine = true;
    00766                 }
    00767
    00768                 if (copyLine)
    00769                 {
    00770                         m_line += '\n';
    00771                         AttachedTransformation()->Put((byte *)m_line.data(), m_line.size(), blocking);
    00772                         return false;
    00773                 }
    00774
    00775                 std::vector<std::string> tokens = Tokenize(m_line);
    00776
    00777                 if (m_algorithm == "DSS" && m_test == "sha")
    00778                 {
    00779                         for (int i = 0; i < tokens.size(); i++)
    00780                         {
    00781                                 if (tokens[i] == "^")
    00782                                         DoTest();
    00783                                 else if (tokens[i] != "")
    00784                                         m_compactString.push_back(atol(tokens[i].c_str()));
    00785                         }
    00786                 }
    00787                 else
    00788                 {
    00789                         if (!m_line.empty() && m_algorithm == "DSS" && m_test != "pqg")
    00790                         {
    00791                                 std::string output = m_line + '\n';
    00792                                 AttachedTransformation()->Put((byte *)output.data(), output.size());
    00793                         }
    00794
    00795                         for (int i = 0; i < tokens.size(); i++)
    00796                         {
    00797                                 if (m_firstLine && m_algorithm != "DSS")
    00798                                 {
    00799                                         if (tokens[i] == "Encrypt" || tokens[i] == "OFB")
    00800                                                 SetEncrypt(true);
    00801                                         else if (tokens[i] == "Decrypt")
    00802                                                 SetEncrypt(false);
    00803                                         else if (tokens[i] == "Modes")
    00804                                                 m_test = "MONTE";
    00805                                 }
    00806                                 else
    00807                                 {
    00808                                         if (tokens[i] != "=")
    00809                                                 continue;
    00810
    00811                                         if (i == 0)
    00812                                                 throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected data: " + m_line);
    00813
    00814                                         const std::string &key = tokens[i-1];
    00815                                         std::string &data = m_data[key];
    00816                                         data = tokens[i+1];
    00817                                         DataType t = m_nameToType[key];
    00818                                         m_typeToName[t] = key;
    00819                                         SecByteBlock data2(data.size() / 2);
    00820                                         StringSource(data, true, new HexDecoder(new ArraySink(data2, data2.size())));
    00821                                         m_data2[t] = data2;
    00822
    00823                                         if (key == m_trigger || (t == OUTPUT && !m_data2[INPUT].empty()))
    00824                                                 DoTest();
    00825                                 }
    00826                         }
    00827                 }
    00828
    00829                 m_firstLine = false;
    00830
    00831                 return false;
    00832         }
    00833
    00834         inline const SecByteBlock & GetData(const std::string &key)
    00835         {
    00836                 return m_data2[m_nameToType[key]];
    00837         }
    00838
    00839         std::string m_algorithm, m_test, m_mode, m_line, m_bracketString, m_trigger;
    00840         unsigned int m_feedbackSize, m_blankLineTransition;
    00841         bool m_encrypt, m_firstLine;
    00842
    00843         typedef std::map<std::string, DataType> NameToTypeMap;
    00844         NameToTypeMap m_nameToType;
    00845         typedef std::map<DataType, std::string> TypeToNameMap;
    00846         TypeToNameMap m_typeToName;
    00847
    00848         typedef std::map<std::string, std::string> Map;
    00849         Map m_data;             // raw data
    00850         typedef std::map<DataType, SecByteBlock> Map2;
    00851         Map2 m_data2;
    00852         int m_count;
    00853
    00854         AutoSeededX917RNG<DES_EDE3> m_rng;
    00855         std::vector<unsigned int> m_compactString;
    00856 };
    00857
    00858 int main (int argc, char **argv)
    00859 {
    00860         std::string algorithm = argv[1];
    00861         std::string pathname = argv[2];
    00862         int i = pathname.find_last_of("\\/");
    00863         std::string filename = pathname.substr(i == std::string::npos ? 0 : i+1);
    00864         std::string mode;
    00865         if (filename[0] == 'S' || filename[0] == 'T')
    00866                 mode = filename.substr(1, 3);
    00867         else
    00868                 mode = filename.substr(0, 3);
    00869         for (i = 0; i<mode.size(); i++)
    00870                 mode[i] = toupper(mode[i]);
    00871         unsigned int feedbackSize = mode == "CFB" ? atoi(filename.substr(filename.find_first_of("0123456789")).c_str()) : 0;
    00872         std::string test;
    00873         if (algorithm == "DSS")
    00874                 test = filename.substr(0, filename.size() - 4);
    00875         else if (filename.find("Monte") != std::string::npos)
    00876                 test = "MONTE";
    00877         else if (filename.find("MCT") != std::string::npos)
    00878                 test = "MCT";
    00879         else
    00880                 test = "KAT";
    00881         bool encrypt = (filename.find("vrct") == std::string::npos);
    00882
    00883         BufferedTransformation *pSink = NULL;
    00884
    00885         if (argc > 3)
    00886         {
    00887                 std::string outDir = argv[3];
    00888                 if (*outDir.rbegin() != '\\' && *outDir.rbegin() != '/')
    00889                         outDir += '/';
    00890                 std::string outPathname = outDir + filename.substr(0, filename.size() - 3) + "rsp";
    00891                 pSink = new FileSink(outPathname.c_str(), false);
    00892         }
    00893         else
    00894                 pSink = new FileSink(cout);
    00895
    00896         FileSource(pathname.c_str(), true, new LineBreakParser(new TestDataParser(algorithm, test, mode, feedbackSize, encrypt, pSink)), false);
    00897         return 0;
    00898 }
    00899 #endif