Crypto++
|
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 }