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