- Main Page
- Namespaces
- Classes
- Files

# datatest.cpp

    00001 #include "factory.h"
    00002 #include "integer.h"
    00003 #include "filters.h"
    00004 #include "hex.h"
    00005 #include "randpool.h"
    00006 #include "files.h"
    00007 #include "trunhash.h"
    00008 #include "queue.h"
    00009 #include "validate.h"
    00010 #include <iostream>
    00011 #include <memory>
    00012
    00013 USING_NAMESPACE(CryptoPP)
    00014 USING_NAMESPACE(std)
    00015
    00016 typedef std::map<std::string, std::string> TestData;
    00017
    00018 class TestFailure : public Exception
    00019 {
    00020 public:
    00021         TestFailure() : Exception(OTHER_ERROR, "Validation test failed") {}
    00022 };
    00023
    00024 static const TestData *s_currentTestData = NULL;
    00025
    00026 static void OutputTestData(const TestData &v)
    00027 {
    00028         for (TestData::const_iterator i = v.begin(); i != v.end(); ++i)
    00029         {
    00030                 cerr << i->first << ": " << i->second << endl;
    00031         }
    00032 }
    00033
    00034 static void SignalTestFailure()
    00035 {
    00036         OutputTestData(*s_currentTestData);
    00037         throw TestFailure();
    00038 }
    00039
    00040 static void SignalTestError()
    00041 {
    00042         OutputTestData(*s_currentTestData);
    00043         throw Exception(Exception::OTHER_ERROR, "Unexpected error during validation test");
    00044 }
    00045
    00046 bool DataExists(const TestData &data, const char *name)
    00047 {
    00048         TestData::const_iterator i = data.find(name);
    00049         return (i != data.end());
    00050 }
    00051
    00052 const std::string & GetRequiredDatum(const TestData &data, const char *name)
    00053 {
    00054         TestData::const_iterator i = data.find(name);
    00055         if (i == data.end())
    00056                 SignalTestError();
    00057         return i->second;
    00058 }
    00059
    00060 void PutDecodedDatumInto(const TestData &data, const char *name, BufferedTransformation &target)
    00061 {
    00062         std::string s1 = GetRequiredDatum(data, name), s2;
    00063
    00064         while (!s1.empty())
    00065         {
    00066                 while (s1[0] == ' ')
    00067                         s1 = s1.substr(1);
    00068
    00069                 int repeat = 1;
    00070                 if (s1[0] == 'r')
    00071                 {
    00072                         repeat = atoi(s1.c_str()+1);
    00073                         s1 = s1.substr(s1.find(' ')+1);
    00074                 }
    00075
    00076                 s2 = ""; // MSVC 6 doesn't have clear();
    00077
    00078                 if (s1[0] == '\"')
    00079                 {
    00080                         s2 = s1.substr(1, s1.find('\"', 1)-1);
    00081                         s1 = s1.substr(s2.length() + 2);
    00082                 }
    00083                 else if (s1.substr(0, 2) == "0x")
    00084                 {
    00085                         StringSource(s1.substr(2, s1.find(' ')), true, new HexDecoder(new StringSink(s2)));
    00086                         s1 = s1.substr(STDMIN(s1.find(' '), s1.length()));
    00087                 }
    00088                 else
    00089                 {
    00090                         StringSource(s1.substr(0, s1.find(' ')), true, new HexDecoder(new StringSink(s2)));
    00091                         s1 = s1.substr(STDMIN(s1.find(' '), s1.length()));
    00092                 }
    00093
    00094                 ByteQueue q;
    00095                 while (repeat--)
    00096                 {
    00097                         q.Put((const byte *)s2.data(), s2.size());
    00098                         if (q.MaxRetrievable() > 4*1024 || repeat == 0)
    00099                                 q.TransferTo(target);
    00100                 }
    00101         }
    00102 }
    00103
    00104 std::string GetDecodedDatum(const TestData &data, const char *name)
    00105 {
    00106         std::string s;
    00107         PutDecodedDatumInto(data, name, StringSink(s).Ref());
    00108         return s;
    00109 }
    00110
    00111 std::string GetOptionalDecodedDatum(const TestData &data, const char *name)
    00112 {
    00113         std::string s;
    00114         if (DataExists(data, name))
    00115                 PutDecodedDatumInto(data, name, StringSink(s).Ref());
    00116         return s;
    00117 }
    00118
    00119 class TestDataNameValuePairs : public NameValuePairs
    00120 {
    00121 public:
    00122         TestDataNameValuePairs(const TestData &data) : m_data(data) {}
    00123
    00124         virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
    00125         {
    00126                 TestData::const_iterator i = m_data.find(name);
    00127                 if (i == m_data.end())
    00128                 {
    00129                         if (std::string(name) == Name::DigestSize() && valueType == typeid(int))
    00130                         {
    00131                                 i = m_data.find("MAC");
    00132                                 if (i == m_data.end())
    00133                                         i = m_data.find("Digest");
    00134                                 if (i == m_data.end())
    00135                                         return false;
    00136
    00137                                 m_temp.resize(0);
    00138                                 PutDecodedDatumInto(m_data, i->first.c_str(), StringSink(m_temp).Ref());
    00139                                 *reinterpret_cast<int *>(pValue) = (int)m_temp.size();
    00140                                 return true;
    00141                         }
    00142                         else
    00143                                 return false;
    00144                 }
    00145
    00146                 const std::string &value = i->second;
    00147
    00148                 if (valueType == typeid(int))
    00149                         *reinterpret_cast<int *>(pValue) = atoi(value.c_str());
    00150                 else if (valueType == typeid(Integer))
    00151                         *reinterpret_cast<Integer *>(pValue) = Integer((std::string(value) + "h").c_str());
    00152                 else if (valueType == typeid(ConstByteArrayParameter))
    00153                 {
    00154                         m_temp.resize(0);
    00155                         PutDecodedDatumInto(m_data, name, StringSink(m_temp).Ref());
    00156                         reinterpret_cast<ConstByteArrayParameter *>(pValue)->Assign((const byte *)m_temp.data(), m_temp.size(), false);
    00157                 }
    00158                 else
    00159                         throw ValueTypeMismatch(name, typeid(std::string), valueType);
    00160
    00161                 return true;
    00162         }
    00163
    00164 private:
    00165         const TestData &m_data;
    00166         mutable std::string m_temp;
    00167 };
    00168
    00169 void TestKeyPairValidAndConsistent(CryptoMaterial &pub, const CryptoMaterial &priv)
    00170 {
    00171         if (!pub.Validate(GlobalRNG(), 3))
    00172                 SignalTestFailure();
    00173         if (!priv.Validate(GlobalRNG(), 3))
    00174                 SignalTestFailure();
    00175
    00176 /*      EqualityComparisonFilter comparison;
    00177         pub.Save(ChannelSwitch(comparison, "0"));
    00178         pub.AssignFrom(priv);
    00179         pub.Save(ChannelSwitch(comparison, "1"));
    00180         comparison.ChannelMessageSeriesEnd("0");
    00181         comparison.ChannelMessageSeriesEnd("1");
    00182 */
    00183 }
    00184
    00185 void TestSignatureScheme(TestData &v)
    00186 {
    00187         std::string name = GetRequiredDatum(v, "Name");
    00188         std::string test = GetRequiredDatum(v, "Test");
    00189
    00190         std::auto_ptr<PK_Signer> signer(ObjectFactoryRegistry<PK_Signer>::Registry().CreateObject(name.c_str()));
    00191         std::auto_ptr<PK_Verifier> verifier(ObjectFactoryRegistry<PK_Verifier>::Registry().CreateObject(name.c_str()));
    00192
    00193         TestDataNameValuePairs pairs(v);
    00194         std::string keyFormat = GetRequiredDatum(v, "KeyFormat");
    00195
    00196         if (keyFormat == "DER")
    00197                 verifier->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref());
    00198         else if (keyFormat == "Component")
    00199                 verifier->AccessMaterial().AssignFrom(pairs);
    00200
    00201         if (test == "Verify" || test == "NotVerify")
    00202         {
    00203                 VerifierFilter verifierFilter(*verifier, NULL, VerifierFilter::SIGNATURE_AT_BEGIN);
    00204                 PutDecodedDatumInto(v, "Signature", verifierFilter);
    00205                 PutDecodedDatumInto(v, "Message", verifierFilter);
    00206                 verifierFilter.MessageEnd();
    00207                 if (verifierFilter.GetLastResult() == (test == "NotVerify"))
    00208                         SignalTestFailure();
    00209         }
    00210         else if (test == "PublicKeyValid")
    00211         {
    00212                 if (!verifier->GetMaterial().Validate(GlobalRNG(), 3))
    00213                         SignalTestFailure();
    00214         }
    00215         else
    00216                 goto privateKeyTests;
    00217
    00218         return;
    00219
    00220 privateKeyTests:
    00221         if (keyFormat == "DER")
    00222                 signer->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref());
    00223         else if (keyFormat == "Component")
    00224                 signer->AccessMaterial().AssignFrom(pairs);
    00225
    00226         if (test == "KeyPairValidAndConsistent")
    00227         {
    00228                 TestKeyPairValidAndConsistent(verifier->AccessMaterial(), signer->GetMaterial());
    00229         }
    00230         else if (test == "Sign")
    00231         {
    00232                 SignerFilter f(GlobalRNG(), *signer, new HexEncoder(new FileSink(cout)));
    00233                 StringSource ss(GetDecodedDatum(v, "Message"), true, new Redirector(f));
    00234                 SignalTestFailure();
    00235         }
    00236         else if (test == "DeterministicSign")
    00237         {
    00238                 SignalTestError();
    00239                 assert(false);  // TODO: implement
    00240         }
    00241         else if (test == "RandomSign")
    00242         {
    00243                 SignalTestError();
    00244                 assert(false);  // TODO: implement
    00245         }
    00246         else if (test == "GenerateKey")
    00247         {
    00248                 SignalTestError();
    00249                 assert(false);
    00250         }
    00251         else
    00252         {
    00253                 SignalTestError();
    00254                 assert(false);
    00255         }
    00256 }
    00257
    00258 void TestAsymmetricCipher(TestData &v)
    00259 {
    00260         std::string name = GetRequiredDatum(v, "Name");
    00261         std::string test = GetRequiredDatum(v, "Test");
    00262
    00263         std::auto_ptr<PK_Encryptor> encryptor(ObjectFactoryRegistry<PK_Encryptor>::Registry().CreateObject(name.c_str()));
    00264         std::auto_ptr<PK_Decryptor> decryptor(ObjectFactoryRegistry<PK_Decryptor>::Registry().CreateObject(name.c_str()));
    00265
    00266         std::string keyFormat = GetRequiredDatum(v, "KeyFormat");
    00267
    00268         if (keyFormat == "DER")
    00269         {
    00270                 decryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref());
    00271                 encryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref());
    00272         }
    00273         else if (keyFormat == "Component")
    00274         {
    00275                 TestDataNameValuePairs pairs(v);
    00276                 decryptor->AccessMaterial().AssignFrom(pairs);
    00277                 encryptor->AccessMaterial().AssignFrom(pairs);
    00278         }
    00279
    00280         if (test == "DecryptMatch")
    00281         {
    00282                 std::string decrypted, expected = GetDecodedDatum(v, "Plaintext");
    00283                 StringSource ss(GetDecodedDatum(v, "Ciphertext"), true, new PK_DecryptorFilter(GlobalRNG(), *decryptor, new StringSink(decrypted)));
    00284                 if (decrypted != expected)
    00285                         SignalTestFailure();
    00286         }
    00287         else if (test == "KeyPairValidAndConsistent")
    00288         {
    00289                 TestKeyPairValidAndConsistent(encryptor->AccessMaterial(), decryptor->GetMaterial());
    00290         }
    00291         else
    00292         {
    00293                 SignalTestError();
    00294                 assert(false);
    00295         }
    00296 }
    00297
    00298 void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
    00299 {
    00300         std::string name = GetRequiredDatum(v, "Name");
    00301         std::string test = GetRequiredDatum(v, "Test");
    00302
    00303         std::string key = GetDecodedDatum(v, "Key");
    00304         std::string plaintext = GetDecodedDatum(v, "Plaintext");
    00305
    00306         TestDataNameValuePairs testDataPairs(v);
    00307         CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
    00308
    00309         if (test == "Encrypt" || test == "EncryptXorDigest" || test == "Resync")
    00310         {
    00311                 static member_ptr<SymmetricCipher> encryptor, decryptor;
    00312                 static std::string lastName;
    00313
    00314                 if (name != lastName)
    00315                 {
    00316                         encryptor.reset(ObjectFactoryRegistry<SymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
    00317                         decryptor.reset(ObjectFactoryRegistry<SymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
    00318                         lastName = name;
    00319                 }
    00320
    00321                 ConstByteArrayParameter iv;
    00322                 if (pairs.GetValue(Name::IV(), iv) && iv.size() != encryptor->IVSize())
    00323                         SignalTestFailure();
    00324
    00325                 if (test == "Resync")
    00326                 {
    00327                         encryptor->Resynchronize(iv.begin(), (int)iv.size());
    00328                         decryptor->Resynchronize(iv.begin(), (int)iv.size());
    00329                 }
    00330                 else
    00331                 {
    00332                         encryptor->SetKey((const byte *)key.data(), key.size(), pairs);
    00333                         decryptor->SetKey((const byte *)key.data(), key.size(), pairs);
    00334                 }
    00335
    00336                 int seek = pairs.GetIntValueWithDefault("Seek", 0);
    00337                 if (seek)
    00338                 {
    00339                         encryptor->Seek(seek);
    00340                         decryptor->Seek(seek);
    00341                 }
    00342                 std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
    00343                 StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(encrypted), StreamTransformationFilter::NO_PADDING));
    00344                 ss.Pump(plaintext.size()/2 + 1);
    00345                 ss.PumpAll();
    00346                 /*{
    00347                         std::string z;
    00348                         encryptor->Seek(seek);
    00349                         StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(z), StreamTransformationFilter::NO_PADDING));
    00350                         while (ss.Pump(64)) {}
    00351                         ss.PumpAll();
    00352                         for (int i=0; i<z.length(); i++)
    00353                                 assert(encrypted[i] == z[i]);
    00354                 }*/
    00355                 if (test != "EncryptXorDigest")
    00356                         ciphertext = GetDecodedDatum(v, "Ciphertext");
    00357                 else
    00358                 {
    00359                         ciphertextXorDigest = GetDecodedDatum(v, "CiphertextXorDigest");
    00360                         xorDigest.append(encrypted, 0, 64);
    00361                         for (size_t i=64; i<encrypted.size(); i++)
    00362                                 xorDigest[i%64] ^= encrypted[i];
    00363                 }
    00364                 if (test != "EncryptXorDigest" ? encrypted != ciphertext : xorDigest != ciphertextXorDigest)
    00365                 {
    00366                         std::cout << "incorrectly encrypted: ";
    00367                         StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
    00368                         xx.Pump(256); xx.Flush(false);
    00369                         std::cout << "\n";
    00370                         SignalTestFailure();
    00371                 }
    00372                 std::string decrypted;
    00373                 StringSource dd(encrypted, false, new StreamTransformationFilter(*decryptor, new StringSink(decrypted), StreamTransformationFilter::NO_PADDING));
    00374                 dd.Pump(plaintext.size()/2 + 1);
    00375                 dd.PumpAll();
    00376                 if (decrypted != plaintext)
    00377                 {
    00378                         std::cout << "incorrectly decrypted: ";
    00379                         StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
    00380                         xx.Pump(256); xx.Flush(false);
    00381                         std::cout << "\n";
    00382                         SignalTestFailure();
    00383                 }
    00384         }
    00385         else
    00386         {
    00387                 std::cout << "unexpected test name\n";
    00388                 SignalTestError();
    00389         }
    00390 }
    00391
    00392 void TestAuthenticatedSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
    00393 {
    00394         std::string type = GetRequiredDatum(v, "AlgorithmType");
    00395         std::string name = GetRequiredDatum(v, "Name");
    00396         std::string test = GetRequiredDatum(v, "Test");
    00397         std::string key = GetDecodedDatum(v, "Key");
    00398
    00399         std::string plaintext = GetOptionalDecodedDatum(v, "Plaintext");
    00400         std::string ciphertext = GetOptionalDecodedDatum(v, "Ciphertext");
    00401         std::string header = GetOptionalDecodedDatum(v, "Header");
    00402         std::string footer = GetOptionalDecodedDatum(v, "Footer");
    00403         std::string mac = GetOptionalDecodedDatum(v, "MAC");
    00404
    00405         TestDataNameValuePairs testDataPairs(v);
    00406         CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
    00407
    00408         if (test == "Encrypt" || test == "EncryptXorDigest" || test == "NotVerify")
    00409         {
    00410                 member_ptr<AuthenticatedSymmetricCipher> asc1, asc2;
    00411                 asc1.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
    00412                 asc2.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
    00413                 asc1->SetKey((const byte *)key.data(), key.size(), pairs);
    00414                 asc2->SetKey((const byte *)key.data(), key.size(), pairs);
    00415
    00416                 std::string encrypted, decrypted;
    00417                 AuthenticatedEncryptionFilter ef(*asc1, new StringSink(encrypted));
    00418                 bool macAtBegin = !mac.empty() && !GlobalRNG().GenerateBit();   // test both ways randomly
    00419                 AuthenticatedDecryptionFilter df(*asc2, new StringSink(decrypted), macAtBegin ? AuthenticatedDecryptionFilter::MAC_AT_BEGIN : 0);
    00420
    00421                 if (asc1->NeedsPrespecifiedDataLengths())
    00422                 {
    00423                         asc1->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
    00424                         asc2->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
    00425                 }
    00426
    00427                 StringStore sh(header), sp(plaintext), sc(ciphertext), sf(footer), sm(mac);
    00428
    00429                 if (macAtBegin)
    00430                         sm.TransferTo(df);
    00431                 sh.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
    00432                 sc.TransferTo(df);
    00433                 sf.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
    00434                 if (!macAtBegin)
    00435                         sm.TransferTo(df);
    00436                 df.MessageEnd();
    00437
    00438                 sh.TransferTo(ef, sh.MaxRetrievable()/2+1, AAD_CHANNEL);
    00439                 sh.TransferTo(ef, LWORD_MAX, AAD_CHANNEL);
    00440                 sp.TransferTo(ef, sp.MaxRetrievable()/2+1);
    00441                 sp.TransferTo(ef);
    00442                 sf.TransferTo(ef, sf.MaxRetrievable()/2+1, AAD_CHANNEL);
    00443                 sf.TransferTo(ef, LWORD_MAX, AAD_CHANNEL);
    00444                 ef.MessageEnd();
    00445
    00446                 if (test == "Encrypt" && encrypted != ciphertext+mac)
    00447                 {
    00448                         std::cout << "incorrectly encrypted: ";
    00449                         StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
    00450                         xx.Pump(256); xx.Flush(false);
    00451                         std::cout << "\n";
    00452                         SignalTestFailure();
    00453                 }
    00454                 if (test == "Encrypt" && decrypted != plaintext)
    00455                 {
    00456                         std::cout << "incorrectly decrypted: ";
    00457                         StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
    00458                         xx.Pump(256); xx.Flush(false);
    00459                         std::cout << "\n";
    00460                         SignalTestFailure();
    00461                 }
    00462
    00463                 if (ciphertext.size()+mac.size()-plaintext.size() != asc1->DigestSize())
    00464                 {
    00465                         std::cout << "bad MAC size\n";
    00466                         SignalTestFailure();
    00467                 }
    00468                 if (df.GetLastResult() != (test == "Encrypt"))
    00469                 {
    00470                         std::cout << "MAC incorrectly verified\n";
    00471                         SignalTestFailure();
    00472                 }
    00473         }
    00474         else
    00475         {
    00476                 std::cout << "unexpected test name\n";
    00477                 SignalTestError();
    00478         }
    00479 }
    00480
    00481 void TestDigestOrMAC(TestData &v, bool testDigest)
    00482 {
    00483         std::string name = GetRequiredDatum(v, "Name");
    00484         std::string test = GetRequiredDatum(v, "Test");
    00485         const char *digestName = testDigest ? "Digest" : "MAC";
    00486
    00487         member_ptr<MessageAuthenticationCode> mac;
    00488         member_ptr<HashTransformation> hash;
    00489         HashTransformation *pHash = NULL;
    00490
    00491         TestDataNameValuePairs pairs(v);
    00492
    00493         if (testDigest)
    00494         {
    00495                 hash.reset(ObjectFactoryRegistry<HashTransformation>::Registry().CreateObject(name.c_str()));
    00496                 pHash = hash.get();
    00497         }
    00498         else
    00499         {
    00500                 mac.reset(ObjectFactoryRegistry<MessageAuthenticationCode>::Registry().CreateObject(name.c_str()));
    00501                 pHash = mac.get();
    00502                 std::string key = GetDecodedDatum(v, "Key");
    00503                 mac->SetKey((const byte *)key.c_str(), key.size(), pairs);
    00504         }
    00505
    00506         if (test == "Verify" || test == "VerifyTruncated" || test == "NotVerify")
    00507         {
    00508                 int digestSize = -1;
    00509                 if (test == "VerifyTruncated")
    00510                         pairs.GetIntValue(Name::DigestSize(), digestSize);
    00511                 HashVerificationFilter verifierFilter(*pHash, NULL, HashVerificationFilter::HASH_AT_BEGIN, digestSize);
    00512                 PutDecodedDatumInto(v, digestName, verifierFilter);
    00513                 PutDecodedDatumInto(v, "Message", verifierFilter);
    00514                 verifierFilter.MessageEnd();
    00515                 if (verifierFilter.GetLastResult() == (test == "NotVerify"))
    00516                         SignalTestFailure();
    00517         }
    00518         else
    00519         {
    00520                 SignalTestError();
    00521                 assert(false);
    00522         }
    00523 }
    00524
    00525 bool GetField(std::istream &is, std::string &name, std::string &value)
    00526 {
    00527         name.resize(0);         // GCC workaround: 2.95.3 doesn't have clear()
    00528         is >> name;
    00529         if (name.empty())
    00530                 return false;
    00531
    00532         if (name[name.size()-1] != ':')
    00533         {
    00534                 char c;
    00535                 is >> skipws >> c;
    00536                 if (c != ':')
    00537                         SignalTestError();
    00538         }
    00539         else
    00540                 name.erase(name.size()-1);
    00541
    00542         while (is.peek() == ' ')
    00543                 is.ignore(1);
    00544
    00545         // VC60 workaround: getline bug
    00546         char buffer[128];
    00547         value.resize(0);        // GCC workaround: 2.95.3 doesn't have clear()
    00548         bool continueLine;
    00549
    00550         do
    00551         {
    00552                 do
    00553                 {
    00554                         is.get(buffer, sizeof(buffer));
    00555                         value += buffer;
    00556                 }
    00557                 while (buffer[0] != 0);
    00558                 is.clear();
    00559                 is.ignore();
    00560
    00561                 if (!value.empty() && value[value.size()-1] == '\r')
    00562                         value.resize(value.size()-1);
    00563
    00564                 if (!value.empty() && value[value.size()-1] == '\\')
    00565                 {
    00566                         value.resize(value.size()-1);
    00567                         continueLine = true;
    00568                 }
    00569                 else
    00570                         continueLine = false;
    00571
    00572                 std::string::size_type i = value.find('#');
    00573                 if (i != std::string::npos)
    00574                         value.erase(i);
    00575         }
    00576         while (continueLine);
    00577
    00578         return true;
    00579 }
    00580
    00581 void OutputPair(const NameValuePairs &v, const char *name)
    00582 {
    00583         Integer x;
    00584         bool b = v.GetValue(name, x);
    00585         assert(b);
    00586         cout << name << ": \\\n    ";
    00587         x.Encode(HexEncoder(new FileSink(cout), false, 64, "\\\n    ").Ref(), x.MinEncodedSize());
    00588         cout << endl;
    00589 }
    00590
    00591 void OutputNameValuePairs(const NameValuePairs &v)
    00592 {
    00593         std::string names = v.GetValueNames();
    00594         string::size_type i = 0;
    00595         while (i < names.size())
    00596         {
    00597                 string::size_type j = names.find_first_of (';', i);
    00598
    00599                 if (j == string::npos)
    00600                         return;
    00601                 else
    00602                 {
    00603                         std::string name = names.substr(i, j-i);
    00604                         if (name.find(':') == string::npos)
    00605                                 OutputPair(v, name.c_str());
    00606                 }
    00607
    00608                 i = j + 1;
    00609         }
    00610 }
    00611
    00612 void TestDataFile(const std::string &filename, const NameValuePairs &overrideParameters, unsigned int &totalTests, unsigned int &failedTests)
    00613 {
    00614         std::ifstream file(filename.c_str());
    00615         if (!file.good())
    00616                 throw Exception(Exception::OTHER_ERROR, "Can not open file " + filename + " for reading");
    00617         TestData v;
    00618         s_currentTestData = &v;
    00619         std::string name, value, lastAlgName;
    00620
    00621         while (file)
    00622         {
    00623                 while (file.peek() == '#')
    00624                         file.ignore(INT_MAX, '\n');
    00625
    00626                 if (file.peek() == '\n' || file.peek() == '\r')
    00627                         v.clear();
    00628
    00629                 if (!GetField(file, name, value))
    00630                         break;
    00631                 v[name] = value;
    00632
    00633                 if (name == "Test")
    00634                 {
    00635                         bool failed = true;
    00636                         std::string algType = GetRequiredDatum(v, "AlgorithmType");
    00637
    00638                         if (lastAlgName != GetRequiredDatum(v, "Name"))
    00639                         {
    00640                                 lastAlgName = GetRequiredDatum(v, "Name");
    00641                                 cout << "\nTesting " << algType.c_str() << " algorithm " << lastAlgName.c_str() << ".\n";
    00642                         }
    00643
    00644                         try
    00645                         {
    00646                                 if (algType == "Signature")
    00647                                         TestSignatureScheme(v);
    00648                                 else if (algType == "SymmetricCipher")
    00649                                         TestSymmetricCipher(v, overrideParameters);
    00650                                 else if (algType == "AuthenticatedSymmetricCipher")
    00651                                         TestAuthenticatedSymmetricCipher(v, overrideParameters);
    00652                                 else if (algType == "AsymmetricCipher")
    00653                                         TestAsymmetricCipher(v);
    00654                                 else if (algType == "MessageDigest")
    00655                                         TestDigestOrMAC(v, true);
    00656                                 else if (algType == "MAC")
    00657                                         TestDigestOrMAC(v, false);
    00658                                 else if (algType == "FileList")
    00659                                         TestDataFile(GetRequiredDatum(v, "Test"), g_nullNameValuePairs, totalTests, failedTests);
    00660                                 else
    00661                                         SignalTestError();
    00662                                 failed = false;
    00663                         }
    00664                         catch (TestFailure &)
    00665                         {
    00666                                 cout << "\nTest failed.\n";
    00667                         }
    00668                         catch (CryptoPP::Exception &e)
    00669                         {
    00670                                 cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
    00671                         }
    00672                         catch (std::exception &e)
    00673                         {
    00674                                 cout << "\nstd::exception caught: " << e.what() << endl;
    00675                         }
    00676
    00677                         if (failed)
    00678                         {
    00679                                 cout << "Skipping to next test.\n";
    00680                                 failedTests++;
    00681                         }
    00682                         else
    00683                                 cout << "." << flush;
    00684
    00685                         totalTests++;
    00686                 }
    00687         }
    00688 }
    00689
    00690 bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters)
    00691 {
    00692         unsigned int totalTests = 0, failedTests = 0;
    00693         TestDataFile(filename, overrideParameters, totalTests, failedTests);
    00694         cout << "\nTests complete. Total tests = " << totalTests << ". Failed tests = " << failedTests << ".\n";
    00695         if (failedTests != 0)
    00696                 cout << "SOME TESTS FAILED!\n";
    00697         return failedTests == 0;
    00698 }