13 USING_NAMESPACE(CryptoPP)
16 typedef std::map<std::
string, std::
string> TestData;
17 static
bool s_thorough;
22 TestFailure() : Exception(OTHER_ERROR,
"Validation test failed") {}
25 static const TestData *s_currentTestData = NULL;
27 static void OutputTestData(
const TestData &v)
29 for (TestData::const_iterator i = v.begin(); i != v.end(); ++i)
31 cerr << i->first <<
": " << i->second << endl;
35 static void SignalTestFailure()
37 OutputTestData(*s_currentTestData);
41 static void SignalTestError()
43 OutputTestData(*s_currentTestData);
47 bool DataExists(
const TestData &data,
const char *name)
49 TestData::const_iterator i = data.find(name);
50 return (i != data.end());
53 const std::string & GetRequiredDatum(
const TestData &data,
const char *name)
55 TestData::const_iterator i = data.find(name);
68 len = source.
Get(buf+start, len);
69 target.ChannelPut(channel, buf+start, len);
75 std::string s1 = GetRequiredDatum(data, name), s2;
90 repeat = atoi(s1.c_str()+1);
91 s1 = s1.substr(s1.find(
' ')+1);
98 s2 = s1.substr(1, s1.find(
'\"', 1)-1);
99 s1 = s1.substr(s2.length() + 2);
101 else if (s1.substr(0, 2) ==
"0x")
104 s1 = s1.substr(STDMIN(s1.find(
' '), s1.length()));
109 s1 = s1.substr(STDMIN(s1.find(
' '), s1.length()));
114 q.
Put((
const byte *)s2.data(), s2.size());
115 RandomizedTransfer(q, target,
false);
120 RandomizedTransfer(q, target,
true);
123 std::string GetDecodedDatum(
const TestData &data,
const char *name)
126 PutDecodedDatumInto(data, name,
StringSink(s).Ref());
130 std::string GetOptionalDecodedDatum(
const TestData &data,
const char *name)
133 if (DataExists(data, name))
134 PutDecodedDatumInto(data, name,
StringSink(s).Ref());
143 virtual bool GetVoidValue(
const char *name,
const std::type_info &valueType,
void *pValue)
const
145 TestData::const_iterator i = m_data.find(name);
146 if (i == m_data.end())
150 i = m_data.find(
"MAC");
151 if (i == m_data.end())
152 i = m_data.find(
"Digest");
153 if (i == m_data.end())
157 PutDecodedDatumInto(m_data, i->first.c_str(),
StringSink(m_temp).
Ref());
158 *
reinterpret_cast<int *
>(pValue) = (
int)m_temp.size();
165 const std::string &value = i->second;
167 if (valueType ==
typeid(
int))
168 *
reinterpret_cast<int *
>(pValue) = atoi(value.c_str());
169 else if (valueType ==
typeid(
Integer))
170 *reinterpret_cast<Integer *>(pValue) =
Integer((std::string(value) +
"h").c_str());
174 PutDecodedDatumInto(m_data, name,
StringSink(m_temp).Ref());
175 reinterpret_cast<ConstByteArrayParameter *
>(pValue)->Assign((
const byte *)m_temp.data(), m_temp.size(),
false);
184 const TestData &m_data;
185 mutable std::string m_temp;
190 if (!pub.
Validate(GlobalRNG(), 2+s_thorough))
192 if (!priv.
Validate(GlobalRNG(), 2+s_thorough))
203 void TestSignatureScheme(TestData &v)
205 std::string name = GetRequiredDatum(v,
"Name");
206 std::string test = GetRequiredDatum(v,
"Test");
213 if (test ==
"GenerateKey")
215 signer->AccessPrivateKey().GenerateRandom(GlobalRNG(), pairs);
216 verifier->AccessPublicKey().AssignFrom(signer->AccessPrivateKey());
220 std::string keyFormat = GetRequiredDatum(v,
"KeyFormat");
222 if (keyFormat ==
"DER")
223 verifier->AccessMaterial().Load(
StringStore(GetDecodedDatum(v,
"PublicKey")).Ref());
224 else if (keyFormat ==
"Component")
225 verifier->AccessMaterial().AssignFrom(pairs);
227 if (test ==
"Verify" || test ==
"NotVerify")
229 VerifierFilter verifierFilter(*verifier, NULL, VerifierFilter::SIGNATURE_AT_BEGIN);
230 PutDecodedDatumInto(v,
"Signature", verifierFilter);
231 PutDecodedDatumInto(v,
"Message", verifierFilter);
232 verifierFilter.MessageEnd();
233 if (verifierFilter.GetLastResult() == (test ==
"NotVerify"))
237 else if (test ==
"PublicKeyValid")
239 if (!verifier->GetMaterial().Validate(GlobalRNG(), 3))
244 if (keyFormat ==
"DER")
245 signer->AccessMaterial().Load(
StringStore(GetDecodedDatum(v,
"PrivateKey")).Ref());
246 else if (keyFormat ==
"Component")
247 signer->AccessMaterial().AssignFrom(pairs);
250 if (test ==
"GenerateKey" || test ==
"KeyPairValidAndConsistent")
252 TestKeyPairValidAndConsistent(verifier->AccessMaterial(), signer->GetMaterial());
253 VerifierFilter verifierFilter(*verifier, NULL, VerifierFilter::THROW_EXCEPTION);
254 verifierFilter.Put((
const byte *)
"abc", 3);
257 else if (test ==
"Sign")
263 else if (test ==
"DeterministicSign")
268 else if (test ==
"RandomSign")
280 void TestAsymmetricCipher(TestData &v)
282 std::string name = GetRequiredDatum(v,
"Name");
283 std::string test = GetRequiredDatum(v,
"Test");
288 std::string keyFormat = GetRequiredDatum(v,
"KeyFormat");
290 if (keyFormat ==
"DER")
292 decryptor->AccessMaterial().Load(
StringStore(GetDecodedDatum(v,
"PrivateKey")).Ref());
293 encryptor->AccessMaterial().Load(
StringStore(GetDecodedDatum(v,
"PublicKey")).Ref());
295 else if (keyFormat ==
"Component")
298 decryptor->AccessMaterial().AssignFrom(pairs);
299 encryptor->AccessMaterial().AssignFrom(pairs);
302 if (test ==
"DecryptMatch")
304 std::string decrypted, expected = GetDecodedDatum(v,
"Plaintext");
306 if (decrypted != expected)
309 else if (test ==
"KeyPairValidAndConsistent")
311 TestKeyPairValidAndConsistent(encryptor->AccessMaterial(), decryptor->GetMaterial());
320 void TestSymmetricCipher(TestData &v,
const NameValuePairs &overrideParameters)
322 std::string name = GetRequiredDatum(v,
"Name");
323 std::string test = GetRequiredDatum(v,
"Test");
325 std::string key = GetDecodedDatum(v,
"Key");
326 std::string plaintext = GetDecodedDatum(v,
"Plaintext");
331 if (test ==
"Encrypt" || test ==
"EncryptXorDigest" || test ==
"Resync" || test ==
"EncryptionMCT" || test ==
"DecryptionMCT")
334 static std::string lastName;
336 if (name != lastName)
344 if (pairs.GetValue(
Name::IV(), iv) && iv.size() != encryptor->IVSize())
347 if (test ==
"Resync")
354 encryptor->
SetKey((
const byte *)key.data(), key.size(), pairs);
355 decryptor->
SetKey((
const byte *)key.data(), key.size(), pairs);
358 int seek = pairs.GetIntValueWithDefault(
"Seek", 0);
361 encryptor->
Seek(seek);
362 decryptor->
Seek(seek);
365 std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
366 if (test ==
"EncryptionMCT" || test ==
"DecryptionMCT")
369 SecByteBlock buf((byte *)plaintext.data(), plaintext.size()), keybuf((byte *)key.data(), key.size());
371 if (test == "DecryptionMCT")
373 cipher = decryptor.get();
374 ciphertext = GetDecodedDatum(v,
"Ciphertext");
375 buf.Assign((byte *)ciphertext.data(), ciphertext.size());
378 for (
int i=0; i<400; i++)
380 encrypted.reserve(10000 * plaintext.size());
381 for (
int j=0; j<10000; j++)
384 encrypted.append((
char *)buf.begin(), buf.size());
387 encrypted.erase(0, encrypted.size() - keybuf.size());
388 xorbuf(keybuf.begin(), (
const byte *)encrypted.data(), keybuf.size());
389 cipher->
SetKey(keybuf, keybuf.size());
391 encrypted.assign((
char *)buf.begin(), buf.size());
392 ciphertext = GetDecodedDatum(v, test ==
"EncryptionMCT" ?
"Ciphertext" :
"Plaintext");
393 if (encrypted != ciphertext)
395 std::cout <<
"incorrectly encrypted: ";
397 xx.Pump(256); xx.Flush(
false);
405 RandomizedTransfer(
StringStore(plaintext).Ref(), encFilter,
true);
406 encFilter.MessageEnd();
416 if (test !=
"EncryptXorDigest")
417 ciphertext = GetDecodedDatum(v,
"Ciphertext");
420 ciphertextXorDigest = GetDecodedDatum(v,
"CiphertextXorDigest");
421 xorDigest.append(encrypted, 0, 64);
422 for (
size_t i=64; i<encrypted.size(); i++)
423 xorDigest[i%64] ^= encrypted[i];
425 if (test !=
"EncryptXorDigest" ? encrypted != ciphertext : xorDigest != ciphertextXorDigest)
427 std::cout <<
"incorrectly encrypted: ";
429 xx.Pump(2048); xx.Flush(
false);
433 std::string decrypted;
435 RandomizedTransfer(
StringStore(encrypted).Ref(), decFilter,
true);
436 decFilter.MessageEnd();
437 if (decrypted != plaintext)
439 std::cout <<
"incorrectly decrypted: ";
441 xx.Pump(256); xx.Flush(
false);
448 std::cout <<
"unexpected test name\n";
453 void TestAuthenticatedSymmetricCipher(TestData &v,
const NameValuePairs &overrideParameters)
455 std::string type = GetRequiredDatum(v,
"AlgorithmType");
456 std::string name = GetRequiredDatum(v,
"Name");
457 std::string test = GetRequiredDatum(v,
"Test");
458 std::string key = GetDecodedDatum(v,
"Key");
460 std::string plaintext = GetOptionalDecodedDatum(v,
"Plaintext");
461 std::string ciphertext = GetOptionalDecodedDatum(v,
"Ciphertext");
462 std::string header = GetOptionalDecodedDatum(v,
"Header");
463 std::string footer = GetOptionalDecodedDatum(v,
"Footer");
464 std::string mac = GetOptionalDecodedDatum(v,
"MAC");
469 if (test ==
"Encrypt" || test ==
"EncryptXorDigest" || test ==
"NotVerify")
474 asc1->
SetKey((
const byte *)key.data(), key.size(), pairs);
475 asc2->
SetKey((
const byte *)key.data(), key.size(), pairs);
477 std::string encrypted, decrypted;
479 bool macAtBegin = !mac.empty() && !GlobalRNG().
GenerateBit();
488 StringStore sh(header), sp(plaintext), sc(ciphertext), sf(footer), sm(mac);
491 RandomizedTransfer(sm, df,
true);
492 sh.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
493 RandomizedTransfer(sc, df,
true);
494 sf.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
496 RandomizedTransfer(sm, df,
true);
499 RandomizedTransfer(sh, ef,
true, AAD_CHANNEL);
500 RandomizedTransfer(sp, ef,
true);
501 RandomizedTransfer(sf, ef,
true, AAD_CHANNEL);
504 if (test ==
"Encrypt" && encrypted != ciphertext+mac)
506 std::cout <<
"incorrectly encrypted: ";
508 xx.Pump(2048); xx.Flush(
false);
512 if (test ==
"Encrypt" && decrypted != plaintext)
514 std::cout <<
"incorrectly decrypted: ";
516 xx.Pump(256); xx.Flush(
false);
521 if (ciphertext.size()+mac.size()-plaintext.size() != asc1->
DigestSize())
523 std::cout <<
"bad MAC size\n";
526 if (df.GetLastResult() != (test ==
"Encrypt"))
528 std::cout <<
"MAC incorrectly verified\n";
534 std::cout <<
"unexpected test name\n";
539 void TestDigestOrMAC(TestData &v,
bool testDigest)
541 std::string name = GetRequiredDatum(v,
"Name");
542 std::string test = GetRequiredDatum(v,
"Test");
543 const char *digestName = testDigest ?
"Digest" :
"MAC";
560 std::string key = GetDecodedDatum(v,
"Key");
561 mac->
SetKey((
const byte *)key.c_str(), key.size(), pairs);
564 if (test ==
"Verify" || test ==
"VerifyTruncated" || test ==
"NotVerify")
567 if (test ==
"VerifyTruncated")
570 PutDecodedDatumInto(v, digestName, verifierFilter);
571 PutDecodedDatumInto(v,
"Message", verifierFilter);
572 verifierFilter.MessageEnd();
573 if (verifierFilter.GetLastResult() == (test ==
"NotVerify"))
583 bool GetField(std::istream &is, std::string &name, std::string &value)
590 if (name[name.size()-1] !=
':')
598 name.erase(name.size()-1);
600 while (is.peek() ==
' ')
612 is.get(buffer,
sizeof(buffer));
615 while (buffer[0] != 0);
619 if (!value.empty() && value[value.size()-1] ==
'\r')
620 value.resize(value.size()-1);
622 if (!value.empty() && value[value.size()-1] ==
'\\')
624 value.resize(value.size()-1);
628 continueLine =
false;
630 std::string::size_type i = value.find(
'#');
631 if (i != std::string::npos)
634 while (continueLine);
644 cout << name <<
": \\\n ";
652 string::size_type i = 0;
653 while (i < names.size())
655 string::size_type j = names.find_first_of (
';', i);
657 if (j == string::npos)
661 std::string name = names.substr(i, j-i);
662 if (name.find(
':') == string::npos)
663 OutputPair(v, name.c_str());
670 void TestDataFile(
const std::string &filename,
const NameValuePairs &overrideParameters,
unsigned int &totalTests,
unsigned int &failedTests)
672 std::ifstream file(filename.c_str());
676 s_currentTestData = &v;
677 std::string name, value, lastAlgName;
681 while (file.peek() ==
'#')
682 file.ignore(INT_MAX,
'\n');
684 if (file.peek() ==
'\n' || file.peek() ==
'\r')
687 if (!GetField(file, name, value))
691 if (name ==
"Test" && (s_thorough || v[
"SlowTest"] !=
"1"))
694 std::string algType = GetRequiredDatum(v,
"AlgorithmType");
696 if (lastAlgName != GetRequiredDatum(v,
"Name"))
698 lastAlgName = GetRequiredDatum(v,
"Name");
699 cout <<
"\nTesting " << algType.c_str() <<
" algorithm " << lastAlgName.c_str() <<
".\n";
704 if (algType ==
"Signature")
705 TestSignatureScheme(v);
706 else if (algType ==
"SymmetricCipher")
707 TestSymmetricCipher(v, overrideParameters);
708 else if (algType ==
"AuthenticatedSymmetricCipher")
709 TestAuthenticatedSymmetricCipher(v, overrideParameters);
710 else if (algType ==
"AsymmetricCipher")
711 TestAsymmetricCipher(v);
712 else if (algType ==
"MessageDigest")
713 TestDigestOrMAC(v,
true);
714 else if (algType ==
"MAC")
715 TestDigestOrMAC(v,
false);
716 else if (algType ==
"FileList")
717 TestDataFile(GetRequiredDatum(v,
"Test"), g_nullNameValuePairs, totalTests, failedTests);
724 cout <<
"\nTest failed.\n";
726 catch (CryptoPP::Exception &e)
728 cout <<
"\nCryptoPP::Exception caught: " << e.what() << endl;
730 catch (std::exception &e)
732 cout <<
"\nstd::exception caught: " << e.what() << endl;
737 cout <<
"Skipping to next test.\n";
741 cout <<
"." << flush;
748 bool RunTestDataFile(
const char *filename,
const NameValuePairs &overrideParameters,
bool thorough)
750 s_thorough = thorough;
751 unsigned int totalTests = 0, failedTests = 0;
752 TestDataFile(filename, overrideParameters, totalTests, failedTests);
753 cout << dec <<
"\nTests complete. Total tests = " << totalTests <<
". Failed tests = " << failedTests <<
".\n";
754 if (failedTests != 0)
755 cout <<
"SOME TESTS FAILED!\n";
756 return failedTests == 0;