• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

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

Generated on Mon Aug 9 2010 15:56:33 for Crypto++ by  doxygen 1.7.1