Crypto++  5.6.3
Free C++ class library of cryptographic schemes
datatest.cpp
1 // datatest.cpp - written and placed in the public domain by Wei Dai
2 
3 #define CRYPTOPP_DEFAULT_NO_DLL
4 #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
5 
6 #include "cryptlib.h"
7 #include "factory.h"
8 #include "integer.h"
9 #include "filters.h"
10 #include "hex.h"
11 #include "randpool.h"
12 #include "files.h"
13 #include "trunhash.h"
14 #include "queue.h"
15 #include "smartptr.h"
16 #include "validate.h"
17 #include "hkdf.h"
18 #include "stdcpp.h"
19 #include <iostream>
20 
21 // Aggressive stack checking with VS2005 SP1 and above.
22 #if (CRYPTOPP_MSC_VERSION >= 1410)
23 # pragma strict_gs_check (on)
24 #endif
25 
26 #if defined(__COVERITY__)
27 extern "C" void __coverity_tainted_data_sanitize__(void *);
28 #endif
29 
30 USING_NAMESPACE(CryptoPP)
31 USING_NAMESPACE(std)
32 
33 typedef std::map<std::string, std::string> TestData;
34 static bool s_thorough = false;
35 
36 class TestFailure : public Exception
37 {
38 public:
39  TestFailure() : Exception(OTHER_ERROR, "Validation test failed") {}
40 };
41 
42 static const TestData *s_currentTestData = NULL;
43 
44 static void OutputTestData(const TestData &v)
45 {
46  for (TestData::const_iterator i = v.begin(); i != v.end(); ++i)
47  {
48  cerr << i->first << ": " << i->second << endl;
49  }
50 }
51 
52 static void SignalTestFailure()
53 {
54  OutputTestData(*s_currentTestData);
55  throw TestFailure();
56 }
57 
58 static void SignalTestError()
59 {
60  OutputTestData(*s_currentTestData);
61  throw Exception(Exception::OTHER_ERROR, "Unexpected error during validation test");
62 }
63 
64 bool DataExists(const TestData &data, const char *name)
65 {
66  TestData::const_iterator i = data.find(name);
67  return (i != data.end());
68 }
69 
70 const std::string & GetRequiredDatum(const TestData &data, const char *name)
71 {
72  TestData::const_iterator i = data.find(name);
73  if (i == data.end())
74  SignalTestError();
75  return i->second;
76 }
77 
78 void RandomizedTransfer(BufferedTransformation &source, BufferedTransformation &target, bool finish, const std::string &channel=DEFAULT_CHANNEL)
79 {
80  while (source.MaxRetrievable() > (finish ? 0 : 4096))
81  {
82  byte buf[4096+64];
83  size_t start = GlobalRNG().GenerateWord32(0, 63);
84  size_t len = GlobalRNG().GenerateWord32(1, UnsignedMin(4096U, 3*source.MaxRetrievable()/2));
85  len = source.Get(buf+start, len);
86  target.ChannelPut(channel, buf+start, len);
87  }
88 }
89 
90 void PutDecodedDatumInto(const TestData &data, const char *name, BufferedTransformation &target)
91 {
92  std::string s1 = GetRequiredDatum(data, name), s2;
93  ByteQueue q;
94 
95  while (!s1.empty())
96  {
97  while (s1[0] == ' ')
98  {
99  s1 = s1.substr(1);
100  if (s1.empty())
101  goto end; // avoid invalid read if s1 is empty
102  }
103 
104  int repeat = 1;
105  if (s1[0] == 'r')
106  {
107  repeat = atoi(s1.c_str()+1);
108  s1 = s1.substr(s1.find(' ')+1);
109  }
110 
111  s2 = ""; // MSVC 6 doesn't have clear();
112 
113  if (s1[0] == '\"')
114  {
115  s2 = s1.substr(1, s1.find('\"', 1)-1);
116  s1 = s1.substr(s2.length() + 2);
117  }
118  else if (s1.substr(0, 2) == "0x")
119  {
120  StringSource(s1.substr(2, s1.find(' ')), true, new HexDecoder(new StringSink(s2)));
121  s1 = s1.substr(STDMIN(s1.find(' '), s1.length()));
122  }
123  else
124  {
125  StringSource(s1.substr(0, s1.find(' ')), true, new HexDecoder(new StringSink(s2)));
126  s1 = s1.substr(STDMIN(s1.find(' '), s1.length()));
127  }
128 
129  while (repeat--)
130  {
131  q.Put((const byte *)s2.data(), s2.size());
132  RandomizedTransfer(q, target, false);
133  }
134  }
135 
136 end:
137  RandomizedTransfer(q, target, true);
138 }
139 
140 std::string GetDecodedDatum(const TestData &data, const char *name)
141 {
142  std::string s;
143  PutDecodedDatumInto(data, name, StringSink(s).Ref());
144  return s;
145 }
146 
147 std::string GetOptionalDecodedDatum(const TestData &data, const char *name)
148 {
149  std::string s;
150  if (DataExists(data, name))
151  PutDecodedDatumInto(data, name, StringSink(s).Ref());
152  return s;
153 }
154 
156 {
157 public:
158  TestDataNameValuePairs(const TestData &data) : m_data(data) {}
159 
160  virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
161  {
162  TestData::const_iterator i = m_data.find(name);
163  if (i == m_data.end())
164  {
165  if (std::string(name) == Name::DigestSize() && valueType == typeid(int))
166  {
167  i = m_data.find("MAC");
168  if (i == m_data.end())
169  i = m_data.find("Digest");
170  if (i == m_data.end())
171  return false;
172 
173  m_temp.resize(0);
174  PutDecodedDatumInto(m_data, i->first.c_str(), StringSink(m_temp).Ref());
175  *reinterpret_cast<int *>(pValue) = (int)m_temp.size();
176  return true;
177  }
178  else
179  return false;
180  }
181 
182  const std::string &value = i->second;
183 
184  if (valueType == typeid(int))
185  *reinterpret_cast<int *>(pValue) = atoi(value.c_str());
186  else if (valueType == typeid(Integer))
187  *reinterpret_cast<Integer *>(pValue) = Integer((std::string(value) + "h").c_str());
188  else if (valueType == typeid(ConstByteArrayParameter))
189  {
190  m_temp.resize(0);
191  PutDecodedDatumInto(m_data, name, StringSink(m_temp).Ref());
192  reinterpret_cast<ConstByteArrayParameter *>(pValue)->Assign((const byte *)m_temp.data(), m_temp.size(), false);
193  }
194  else
195  throw ValueTypeMismatch(name, typeid(std::string), valueType);
196 
197  return true;
198  }
199 
200 private:
201  const TestData &m_data;
202  mutable std::string m_temp;
203 };
204 
205 void TestKeyPairValidAndConsistent(CryptoMaterial &pub, const CryptoMaterial &priv)
206 {
207  // "!!" converts between bool <-> integral.
208  if (!pub.Validate(GlobalRNG(), 2U+!!s_thorough))
209  SignalTestFailure();
210  if (!priv.Validate(GlobalRNG(), 2U+!!s_thorough))
211  SignalTestFailure();
212 
213  ByteQueue bq1, bq2;
214  pub.Save(bq1);
215  pub.AssignFrom(priv);
216  pub.Save(bq2);
217  if (bq1 != bq2)
218  SignalTestFailure();
219 }
220 
221 void TestSignatureScheme(TestData &v)
222 {
223  std::string name = GetRequiredDatum(v, "Name");
224  std::string test = GetRequiredDatum(v, "Test");
225 
226  member_ptr<PK_Signer> signer(ObjectFactoryRegistry<PK_Signer>::Registry().CreateObject(name.c_str()));
227  member_ptr<PK_Verifier> verifier(ObjectFactoryRegistry<PK_Verifier>::Registry().CreateObject(name.c_str()));
228 
229  TestDataNameValuePairs pairs(v);
230 
231  if (test == "GenerateKey")
232  {
233  signer->AccessPrivateKey().GenerateRandom(GlobalRNG(), pairs);
234  verifier->AccessPublicKey().AssignFrom(signer->AccessPrivateKey());
235  }
236  else
237  {
238  std::string keyFormat = GetRequiredDatum(v, "KeyFormat");
239 
240  if (keyFormat == "DER")
241  verifier->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref());
242  else if (keyFormat == "Component")
243  verifier->AccessMaterial().AssignFrom(pairs);
244 
245  if (test == "Verify" || test == "NotVerify")
246  {
247  VerifierFilter verifierFilter(*verifier, NULL, VerifierFilter::SIGNATURE_AT_BEGIN);
248  PutDecodedDatumInto(v, "Signature", verifierFilter);
249  PutDecodedDatumInto(v, "Message", verifierFilter);
250  verifierFilter.MessageEnd();
251  if (verifierFilter.GetLastResult() == (test == "NotVerify"))
252  SignalTestFailure();
253  return;
254  }
255  else if (test == "PublicKeyValid")
256  {
257  if (!verifier->GetMaterial().Validate(GlobalRNG(), 3))
258  SignalTestFailure();
259  return;
260  }
261 
262  if (keyFormat == "DER")
263  signer->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref());
264  else if (keyFormat == "Component")
265  signer->AccessMaterial().AssignFrom(pairs);
266  }
267 
268  if (test == "GenerateKey" || test == "KeyPairValidAndConsistent")
269  {
270  TestKeyPairValidAndConsistent(verifier->AccessMaterial(), signer->GetMaterial());
271  VerifierFilter verifierFilter(*verifier, NULL, VerifierFilter::THROW_EXCEPTION);
272  verifierFilter.Put((const byte *)"abc", 3);
273  StringSource ss("abc", true, new SignerFilter(GlobalRNG(), *signer, new Redirector(verifierFilter)));
274  }
275  else if (test == "Sign")
276  {
277  SignerFilter f(GlobalRNG(), *signer, new HexEncoder(new FileSink(cout)));
278  StringSource ss(GetDecodedDatum(v, "Message"), true, new Redirector(f));
279  SignalTestFailure();
280  }
281  else if (test == "DeterministicSign")
282  {
283  SignalTestError();
284  assert(false); // TODO: implement
285  }
286  else if (test == "RandomSign")
287  {
288  SignalTestError();
289  assert(false); // TODO: implement
290  }
291  else
292  {
293  SignalTestError();
294  assert(false);
295  }
296 }
297 
298 void TestAsymmetricCipher(TestData &v)
299 {
300  std::string name = GetRequiredDatum(v, "Name");
301  std::string test = GetRequiredDatum(v, "Test");
302 
303  member_ptr<PK_Encryptor> encryptor(ObjectFactoryRegistry<PK_Encryptor>::Registry().CreateObject(name.c_str()));
304  member_ptr<PK_Decryptor> decryptor(ObjectFactoryRegistry<PK_Decryptor>::Registry().CreateObject(name.c_str()));
305 
306  std::string keyFormat = GetRequiredDatum(v, "KeyFormat");
307 
308  if (keyFormat == "DER")
309  {
310  decryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref());
311  encryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref());
312  }
313  else if (keyFormat == "Component")
314  {
315  TestDataNameValuePairs pairs(v);
316  decryptor->AccessMaterial().AssignFrom(pairs);
317  encryptor->AccessMaterial().AssignFrom(pairs);
318  }
319 
320  if (test == "DecryptMatch")
321  {
322  std::string decrypted, expected = GetDecodedDatum(v, "Plaintext");
323  StringSource ss(GetDecodedDatum(v, "Ciphertext"), true, new PK_DecryptorFilter(GlobalRNG(), *decryptor, new StringSink(decrypted)));
324  if (decrypted != expected)
325  SignalTestFailure();
326  }
327  else if (test == "KeyPairValidAndConsistent")
328  {
329  TestKeyPairValidAndConsistent(encryptor->AccessMaterial(), decryptor->GetMaterial());
330  }
331  else
332  {
333  SignalTestError();
334  assert(false);
335  }
336 }
337 
338 void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
339 {
340  std::string name = GetRequiredDatum(v, "Name");
341  std::string test = GetRequiredDatum(v, "Test");
342 
343  std::string key = GetDecodedDatum(v, "Key");
344  std::string plaintext = GetDecodedDatum(v, "Plaintext");
345 
346  TestDataNameValuePairs testDataPairs(v);
347  CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
348 
349  if (test == "Encrypt" || test == "EncryptXorDigest" || test == "Resync" || test == "EncryptionMCT" || test == "DecryptionMCT")
350  {
351  static member_ptr<SymmetricCipher> encryptor, decryptor;
352  static std::string lastName;
353 
354  if (name != lastName)
355  {
356  encryptor.reset(ObjectFactoryRegistry<SymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
357  decryptor.reset(ObjectFactoryRegistry<SymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
358  lastName = name;
359  }
360 
362  if (pairs.GetValue(Name::IV(), iv) && iv.size() != encryptor->IVSize())
363  SignalTestFailure();
364 
365  if (test == "Resync")
366  {
367  encryptor->Resynchronize(iv.begin(), (int)iv.size());
368  decryptor->Resynchronize(iv.begin(), (int)iv.size());
369  }
370  else
371  {
372  encryptor->SetKey((const byte *)key.data(), key.size(), pairs);
373  decryptor->SetKey((const byte *)key.data(), key.size(), pairs);
374  }
375 
376  int seek = pairs.GetIntValueWithDefault("Seek", 0);
377  if (seek)
378  {
379  encryptor->Seek(seek);
380  decryptor->Seek(seek);
381  }
382 
383  std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
384  if (test == "EncryptionMCT" || test == "DecryptionMCT")
385  {
386  SymmetricCipher *cipher = encryptor.get();
387  SecByteBlock buf((byte *)plaintext.data(), plaintext.size()), keybuf((byte *)key.data(), key.size());
388 
389  if (test == "DecryptionMCT")
390  {
391  cipher = decryptor.get();
392  ciphertext = GetDecodedDatum(v, "Ciphertext");
393  buf.Assign((byte *)ciphertext.data(), ciphertext.size());
394  }
395 
396  for (int i=0; i<400; i++)
397  {
398  encrypted.reserve(10000 * plaintext.size());
399  for (int j=0; j<10000; j++)
400  {
401  cipher->ProcessString(buf.begin(), buf.size());
402  encrypted.append((char *)buf.begin(), buf.size());
403  }
404 
405  encrypted.erase(0, encrypted.size() - keybuf.size());
406  xorbuf(keybuf.begin(), (const byte *)encrypted.data(), keybuf.size());
407  cipher->SetKey(keybuf, keybuf.size());
408  }
409  encrypted.assign((char *)buf.begin(), buf.size());
410  ciphertext = GetDecodedDatum(v, test == "EncryptionMCT" ? "Ciphertext" : "Plaintext");
411  if (encrypted != ciphertext)
412  {
413  std::cout << "incorrectly encrypted: ";
414  StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
415  xx.Pump(256); xx.Flush(false);
416  std::cout << "\n";
417  SignalTestFailure();
418  }
419  return;
420  }
421 
423  RandomizedTransfer(StringStore(plaintext).Ref(), encFilter, true);
424  encFilter.MessageEnd();
425  /*{
426  std::string z;
427  encryptor->Seek(seek);
428  StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(z), StreamTransformationFilter::NO_PADDING));
429  while (ss.Pump(64)) {}
430  ss.PumpAll();
431  for (int i=0; i<z.length(); i++)
432  assert(encrypted[i] == z[i]);
433  }*/
434  if (test != "EncryptXorDigest")
435  ciphertext = GetDecodedDatum(v, "Ciphertext");
436  else
437  {
438  ciphertextXorDigest = GetDecodedDatum(v, "CiphertextXorDigest");
439  xorDigest.append(encrypted, 0, 64);
440  for (size_t i=64; i<encrypted.size(); i++)
441  xorDigest[i%64] ^= encrypted[i];
442  }
443  if (test != "EncryptXorDigest" ? encrypted != ciphertext : xorDigest != ciphertextXorDigest)
444  {
445  std::cout << "incorrectly encrypted: ";
446  StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
447  xx.Pump(2048); xx.Flush(false);
448  std::cout << "\n";
449  SignalTestFailure();
450  }
451  std::string decrypted;
453  RandomizedTransfer(StringStore(encrypted).Ref(), decFilter, true);
454  decFilter.MessageEnd();
455  if (decrypted != plaintext)
456  {
457  std::cout << "incorrectly decrypted: ";
458  StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
459  xx.Pump(256); xx.Flush(false);
460  std::cout << "\n";
461  SignalTestFailure();
462  }
463  }
464  else
465  {
466  std::cout << "unexpected test name\n";
467  SignalTestError();
468  }
469 }
470 
471 void TestAuthenticatedSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
472 {
473  std::string type = GetRequiredDatum(v, "AlgorithmType");
474  std::string name = GetRequiredDatum(v, "Name");
475  std::string test = GetRequiredDatum(v, "Test");
476  std::string key = GetDecodedDatum(v, "Key");
477 
478  std::string plaintext = GetOptionalDecodedDatum(v, "Plaintext");
479  std::string ciphertext = GetOptionalDecodedDatum(v, "Ciphertext");
480  std::string header = GetOptionalDecodedDatum(v, "Header");
481  std::string footer = GetOptionalDecodedDatum(v, "Footer");
482  std::string mac = GetOptionalDecodedDatum(v, "MAC");
483 
484  TestDataNameValuePairs testDataPairs(v);
485  CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
486 
487  if (test == "Encrypt" || test == "EncryptXorDigest" || test == "NotVerify")
488  {
490  asc1.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
491  asc2.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
492  asc1->SetKey((const byte *)key.data(), key.size(), pairs);
493  asc2->SetKey((const byte *)key.data(), key.size(), pairs);
494 
495  std::string encrypted, decrypted;
496  AuthenticatedEncryptionFilter ef(*asc1, new StringSink(encrypted));
497  bool macAtBegin = !mac.empty() && !GlobalRNG().GenerateBit(); // test both ways randomly
499 
500  if (asc1->NeedsPrespecifiedDataLengths())
501  {
502  asc1->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
503  asc2->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
504  }
505 
506  StringStore sh(header), sp(plaintext), sc(ciphertext), sf(footer), sm(mac);
507 
508  if (macAtBegin)
509  RandomizedTransfer(sm, df, true);
510  sh.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
511  RandomizedTransfer(sc, df, true);
512  sf.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
513  if (!macAtBegin)
514  RandomizedTransfer(sm, df, true);
515  df.MessageEnd();
516 
517  RandomizedTransfer(sh, ef, true, AAD_CHANNEL);
518  RandomizedTransfer(sp, ef, true);
519  RandomizedTransfer(sf, ef, true, AAD_CHANNEL);
520  ef.MessageEnd();
521 
522  if (test == "Encrypt" && encrypted != ciphertext+mac)
523  {
524  std::cout << "incorrectly encrypted: ";
525  StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
526  xx.Pump(2048); xx.Flush(false);
527  std::cout << "\n";
528  SignalTestFailure();
529  }
530  if (test == "Encrypt" && decrypted != plaintext)
531  {
532  std::cout << "incorrectly decrypted: ";
533  StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
534  xx.Pump(256); xx.Flush(false);
535  std::cout << "\n";
536  SignalTestFailure();
537  }
538 
539  if (ciphertext.size()+mac.size()-plaintext.size() != asc1->DigestSize())
540  {
541  std::cout << "bad MAC size\n";
542  SignalTestFailure();
543  }
544  if (df.GetLastResult() != (test == "Encrypt"))
545  {
546  std::cout << "MAC incorrectly verified\n";
547  SignalTestFailure();
548  }
549  }
550  else
551  {
552  std::cout << "unexpected test name\n";
553  SignalTestError();
554  }
555 }
556 
557 void TestDigestOrMAC(TestData &v, bool testDigest)
558 {
559  std::string name = GetRequiredDatum(v, "Name");
560  std::string test = GetRequiredDatum(v, "Test");
561  const char *digestName = testDigest ? "Digest" : "MAC";
562 
565  HashTransformation *pHash = NULL;
566 
567  TestDataNameValuePairs pairs(v);
568 
569  if (testDigest)
570  {
571  hash.reset(ObjectFactoryRegistry<HashTransformation>::Registry().CreateObject(name.c_str()));
572  pHash = hash.get();
573  }
574  else
575  {
576  mac.reset(ObjectFactoryRegistry<MessageAuthenticationCode>::Registry().CreateObject(name.c_str()));
577  pHash = mac.get();
578  std::string key = GetDecodedDatum(v, "Key");
579  mac->SetKey((const byte *)key.c_str(), key.size(), pairs);
580  }
581 
582  if (test == "Verify" || test == "VerifyTruncated" || test == "NotVerify")
583  {
584  int digestSize = -1;
585  if (test == "VerifyTruncated")
586  digestSize = pairs.GetIntValueWithDefault(Name::DigestSize(), digestSize);
587  HashVerificationFilter verifierFilter(*pHash, NULL, HashVerificationFilter::HASH_AT_BEGIN, digestSize);
588  PutDecodedDatumInto(v, digestName, verifierFilter);
589  PutDecodedDatumInto(v, "Message", verifierFilter);
590  verifierFilter.MessageEnd();
591  if (verifierFilter.GetLastResult() == (test == "NotVerify"))
592  SignalTestFailure();
593  }
594  else
595  {
596  SignalTestError();
597  assert(false);
598  }
599 }
600 
601 void TestKeyDerivationFunction(TestData &v)
602 {
603  std::string name = GetRequiredDatum(v, "Name");
604  std::string test = GetRequiredDatum(v, "Test");
605 
606  if(test == "Skip") return;
607  assert(test == "Verify");
608 
609  std::string key = GetDecodedDatum(v, "Key");
610  std::string salt = GetDecodedDatum(v, "Salt");
611  std::string info = GetDecodedDatum(v, "Info");
612  std::string derived = GetDecodedDatum(v, "DerivedKey");
613  std::string t = GetDecodedDatum(v, "DerivedKeyLength");
614 
615  TestDataNameValuePairs pairs(v);
616  unsigned int length = pairs.GetIntValueWithDefault(Name::DerivedKeyLength(), (int)derived.size());
617 
619  kdf.reset(ObjectFactoryRegistry<KeyDerivationFunction>::Registry().CreateObject(name.c_str()));
620 
621  std::string calc; calc.resize(length);
622  unsigned int ret = kdf->DeriveKey(reinterpret_cast<byte*>(&calc[0]), calc.size(),
623  reinterpret_cast<const byte*>(key.data()), key.size(),
624  reinterpret_cast<const byte*>(salt.data()), salt.size(),
625  reinterpret_cast<const byte*>(info.data()), info.size());
626 
627  if(calc != derived || ret != length)
628  SignalTestFailure();
629 }
630 
631 bool GetField(std::istream &is, std::string &name, std::string &value)
632 {
633  name.resize(0); // GCC workaround: 2.95.3 doesn't have clear()
634  is >> name;
635 
636 #if defined(__COVERITY__)
637  // The datafile being read is in /usr/share, and it protected by filesystem ACLs
638  // __coverity_tainted_data_sanitize__(reinterpret_cast<void*>(&name));
639 #endif
640 
641  if (name.empty())
642  return false;
643 
644  if (name[name.size()-1] != ':')
645  {
646  char c;
647  is >> skipws >> c;
648  if (c != ':')
649  SignalTestError();
650  }
651  else
652  name.erase(name.size()-1);
653 
654  while (is.peek() == ' ')
655  is.ignore(1);
656 
657  // VC60 workaround: getline bug
658  char buffer[128];
659  value.resize(0); // GCC workaround: 2.95.3 doesn't have clear()
660  bool continueLine;
661 
662  do
663  {
664  do
665  {
666  is.get(buffer, sizeof(buffer));
667  value += buffer;
668  }
669  while (buffer[0] != 0);
670  is.clear();
671  is.ignore();
672 
673  if (!value.empty() && value[value.size()-1] == '\r')
674  value.resize(value.size()-1);
675 
676  if (!value.empty() && value[value.size()-1] == '\\')
677  {
678  value.resize(value.size()-1);
679  continueLine = true;
680  }
681  else
682  continueLine = false;
683 
684  std::string::size_type i = value.find('#');
685  if (i != std::string::npos)
686  value.erase(i);
687  }
688  while (continueLine);
689 
690  return true;
691 }
692 
693 void OutputPair(const NameValuePairs &v, const char *name)
694 {
695  Integer x;
696  bool b = v.GetValue(name, x);
697  CRYPTOPP_UNUSED(b); assert(b);
698  cout << name << ": \\\n ";
699  x.Encode(HexEncoder(new FileSink(cout), false, 64, "\\\n ").Ref(), x.MinEncodedSize());
700  cout << endl;
701 }
702 
703 void OutputNameValuePairs(const NameValuePairs &v)
704 {
705  std::string names = v.GetValueNames();
706  string::size_type i = 0;
707  while (i < names.size())
708  {
709  string::size_type j = names.find_first_of (';', i);
710 
711  if (j == string::npos)
712  return;
713  else
714  {
715  std::string name = names.substr(i, j-i);
716  if (name.find(':') == string::npos)
717  OutputPair(v, name.c_str());
718  }
719 
720  i = j + 1;
721  }
722 }
723 
724 void TestDataFile(std::string filename, const NameValuePairs &overrideParameters, unsigned int &totalTests, unsigned int &failedTests)
725 {
726  static const std::string dataDirectory(CRYPTOPP_DATA_DIR);
727  if (!dataDirectory.empty())
728  {
729  if(dataDirectory != filename.substr(0, dataDirectory.length()))
730  filename.insert(0, dataDirectory);
731  }
732 
733  std::ifstream file(filename.c_str());
734  if (!file.good())
735  throw Exception(Exception::OTHER_ERROR, "Can not open file " + filename + " for reading");
736  TestData v;
737  s_currentTestData = &v;
738  std::string name, value, lastAlgName;
739 
740  while (file)
741  {
742  while (file.peek() == '#')
743  file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
744 
745  if (file.peek() == '\n' || file.peek() == '\r')
746  v.clear();
747 
748  if (!GetField(file, name, value))
749  break;
750  v[name] = value;
751 
752  if (name == "Test" && (s_thorough || v["SlowTest"] != "1"))
753  {
754  bool failed = true;
755  std::string algType = GetRequiredDatum(v, "AlgorithmType");
756 
757  if (lastAlgName != GetRequiredDatum(v, "Name"))
758  {
759  lastAlgName = GetRequiredDatum(v, "Name");
760  cout << "\nTesting " << algType.c_str() << " algorithm " << lastAlgName.c_str() << ".\n";
761  }
762 
763  try
764  {
765  if (algType == "Signature")
766  TestSignatureScheme(v);
767  else if (algType == "SymmetricCipher")
768  TestSymmetricCipher(v, overrideParameters);
769  else if (algType == "AuthenticatedSymmetricCipher")
770  TestAuthenticatedSymmetricCipher(v, overrideParameters);
771  else if (algType == "AsymmetricCipher")
772  TestAsymmetricCipher(v);
773  else if (algType == "MessageDigest")
774  TestDigestOrMAC(v, true);
775  else if (algType == "MAC")
776  TestDigestOrMAC(v, false);
777  else if (algType == "KDF")
778  TestKeyDerivationFunction(v);
779  else if (algType == "FileList")
780  TestDataFile(GetRequiredDatum(v, "Test"), g_nullNameValuePairs, totalTests, failedTests);
781  else
782  SignalTestError();
783  failed = false;
784  }
785  catch (TestFailure &)
786  {
787  cout << "\nTest failed.\n";
788  }
789  catch (CryptoPP::Exception &e)
790  {
791  cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
792  }
793  catch (std::exception &e)
794  {
795  cout << "\nstd::exception caught: " << e.what() << endl;
796  }
797 
798  if (failed)
799  {
800  cout << "Skipping to next test.\n";
801  failedTests++;
802  }
803  else
804  cout << "." << flush;
805 
806  totalTests++;
807  }
808  }
809 }
810 
811 bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters, bool thorough)
812 {
813  s_thorough = thorough;
814  unsigned int totalTests = 0, failedTests = 0;
815  TestDataFile((filename ? filename : ""), overrideParameters, totalTests, failedTests);
816  cout << dec << "\nTests complete. Total tests = " << totalTests << ". Failed tests = " << failedTests << "." << endl;
817  if (failedTests != 0)
818  cout << "SOME TESTS FAILED!\n";
819  return failedTests == 0;
820 }
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:29
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:139
virtual void AssignFrom(const NameValuePairs &source)=0
Assign values to this object.
virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
Get a named value.
Definition: datatest.cpp:160
const char * DigestSize()
int, in bytes
Definition: argnames.h:78
Indicates the hash is at the beginning of the message (i.e., concatenation of hash+message) ...
Definition: filters.h:555
Filter wrapper for PK_Verifier.
Definition: filters.h:695
virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params=g_nullNameValuePairs)
Sets or reset the key of this object.
Definition: cryptlib.cpp:100
Class file for Randomness Pool.
void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const
Encode in big-endian format.
Definition: integer.cpp:3266
size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
Input a byte for processing on a channel.
Definition: cryptlib.h:1843
virtual bool NeedsPrespecifiedDataLengths() const
Determines if data lengths must be specified prior to inputting data.
Definition: cryptlib.h:1134
Converts given data to base 16.
Definition: hex.h:15
const char * DerivedKeyLength()
int, key derivation, derived key length in bytes
Definition: argnames.h:83
virtual word32 GenerateWord32(word32 min=0, word32 max=0xffffffffUL)
Generate a random 32 bit word in the range min to max, inclusive.
Definition: cryptlib.cpp:301
Decode base 16 data back to bytes.
Definition: hex.h:28
virtual void Save(BufferedTransformation &bt) const
Saves a key to a BufferedTransformation.
Definition: cryptlib.h:2073
Abstract base classes that provide a uniform interface to this library.
Thrown when an unexpected type is encountered.
Definition: cryptlib.h:285
Some other error occurred not belonging to other categories.
Definition: cryptlib.h:158
Indicates the filter should throw a HashVerificationFailed if a failure is encountered.
Definition: filters.h:721
Classes for automatic resource management.
Filter wrapper for PK_Signer.
Definition: filters.h:669
size_t size() const
Length of the memory block.
Definition: algparam.h:93
STL namespace.
std::string GetValueNames() const
Get a list of value names that can be retrieved.
Definition: cryptlib.h:360
void ProcessString(byte *inoutString, size_t length)
Encrypt or decrypt a string of bytes.
Definition: cryptlib.h:855
size_t MinEncodedSize(Signedness sign=UNSIGNED) const
The minimum number of bytes to encode this integer.
Definition: integer.cpp:3254
Combines two sets of NameValuePairs.
Definition: algparam.h:135
SecBlock typedef.
Definition: secblock.h:723
Interface for buffered transformations.
Definition: cryptlib.h:1342
const byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:89
Pointer that overloads operator→
Definition: smartptr.h:39
Classes for an unlimited queue to store bytes.
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:335
Filter wrapper for HashTransformation.
Definition: filters.h:536
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1363
Filter wrapper for decrypting with AuthenticatedSymmetricCipher.
Definition: filters.h:625
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.cpp:41
Filter wrapper for encrypting with AuthenticatedSymmetricCipher.
Definition: filters.h:600
virtual void Resynchronize(const byte *iv, int ivLength=-1)
Resynchronize with an IV.
Definition: cryptlib.h:643
Classes for HexEncoder and HexDecoder.
virtual unsigned int DeriveKey(byte *derived, size_t derivedLen, const byte *secret, size_t secretLen, const byte *salt, size_t saltLen, const byte *info=NULL, size_t infoLen=0) const =0
derive a key from secret
Interface for one direction (encryption or decryption) of a stream cipher or cipher mode...
Definition: cryptlib.h:1089
Multiple precision integer with arithmetic operations.
Definition: integer.h:31
Filter wrapper for PK_Decryptor.
Definition: filters.h:928
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:433
const NameValuePairs & g_nullNameValuePairs
An empty set of name-value pairs.
Definition: cryptlib.cpp:79
String-based implementation of Store interface.
Definition: filters.h:1046
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:397
Redirect input to another BufferedTransformation without owning it.
Definition: filters.h:756
Data structure used to store byte strings.
Definition: queue.h:20
Implementation of BufferedTransformation's attachment interface.
const char * IV()
ConstByteArrayParameter, also accepts const byte * for backwards compatibility.
Definition: argnames.h:21
Filter wrapper for StreamTransformation.
Definition: filters.h:477
virtual unsigned int DigestSize() const =0
Provides the digest size of the hash.
virtual void Seek(lword pos)
Seek to an absolute position.
Definition: cryptlib.h:881
virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0
Check this object for errors.
virtual unsigned int GenerateBit()
Generate new random bit and return it.
Definition: cryptlib.cpp:289
void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Definition: misc.cpp:28
Interface for hash functions and data processing part of MACs.
Definition: cryptlib.h:912
Interface for crypto material, such as public and private keys, and crypto parameters.
Definition: cryptlib.h:2025
virtual lword MaxRetrievable() const
Provides the number of bytes ready for retrieval.
Definition: cryptlib.cpp:499
BufferedTransformation & Ref()
Provides a reference to this object.
Definition: cryptlib.h:1353
void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0)
Prespecifies the data lengths.
Definition: cryptlib.cpp:257
No padding added to a block.
Definition: filters.h:462
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition: cryptlib.cpp:518
Crypto++ library namespace.
Indicates the signature is at the beginning of the message (i.e., concatenation of signature+message)...
Definition: filters.h:713
const std::string AAD_CHANNEL
Channel for additional authenticated data.
Definition: cryptlib.cpp:63
file-based implementation of Sink interface
Definition: files.h:78
Indicates the MAC is at the beginning of the message (i.e., concatenation of mac+message) ...
Definition: filters.h:635
virtual unsigned int IVSize() const
Returns length of the IV accepted by this object.
Definition: cryptlib.h:621
Interface for retrieving values given their names.
Definition: cryptlib.h:277