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;
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 = "";
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
00195
00196
00197
00198
00199
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);
00258 }
00259 else if (test == "RandomSign")
00260 {
00261 SignalTestError();
00262 assert(false);
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
00405
00406
00407
00408
00409
00410
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();
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);
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
00600 char buffer[128];
00601 value.resize(0);
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 }