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