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
498  AuthenticatedDecryptionFilter df(*asc2, new StringSink(decrypted), macAtBegin ? AuthenticatedDecryptionFilter::MAC_AT_BEGIN : 0);
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(const std::string &filename, const NameValuePairs &overrideParameters, unsigned int &totalTests, unsigned int &failedTests)
725 {
726  std::ifstream file(filename.c_str());
727  if (!file.good())
728  throw Exception(Exception::OTHER_ERROR, "Can not open file " + filename + " for reading");
729  TestData v;
730  s_currentTestData = &v;
731  std::string name, value, lastAlgName;
732 
733  while (file)
734  {
735  while (file.peek() == '#')
736  file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
737 
738  if (file.peek() == '\n' || file.peek() == '\r')
739  v.clear();
740 
741  if (!GetField(file, name, value))
742  break;
743  v[name] = value;
744 
745  if (name == "Test" && (s_thorough || v["SlowTest"] != "1"))
746  {
747  bool failed = true;
748  std::string algType = GetRequiredDatum(v, "AlgorithmType");
749 
750  if (lastAlgName != GetRequiredDatum(v, "Name"))
751  {
752  lastAlgName = GetRequiredDatum(v, "Name");
753  cout << "\nTesting " << algType.c_str() << " algorithm " << lastAlgName.c_str() << ".\n";
754  }
755 
756  try
757  {
758  if (algType == "Signature")
759  TestSignatureScheme(v);
760  else if (algType == "SymmetricCipher")
761  TestSymmetricCipher(v, overrideParameters);
762  else if (algType == "AuthenticatedSymmetricCipher")
763  TestAuthenticatedSymmetricCipher(v, overrideParameters);
764  else if (algType == "AsymmetricCipher")
765  TestAsymmetricCipher(v);
766  else if (algType == "MessageDigest")
767  TestDigestOrMAC(v, true);
768  else if (algType == "MAC")
769  TestDigestOrMAC(v, false);
770  else if (algType == "KDF")
771  TestKeyDerivationFunction(v);
772  else if (algType == "FileList")
773  TestDataFile(GetRequiredDatum(v, "Test"), g_nullNameValuePairs, totalTests, failedTests);
774  else
775  SignalTestError();
776  failed = false;
777  }
778  catch (TestFailure &)
779  {
780  cout << "\nTest failed.\n";
781  }
782  catch (CryptoPP::Exception &e)
783  {
784  cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
785  }
786  catch (std::exception &e)
787  {
788  cout << "\nstd::exception caught: " << e.what() << endl;
789  }
790 
791  if (failed)
792  {
793  cout << "Skipping to next test.\n";
794  failedTests++;
795  }
796  else
797  cout << "." << flush;
798 
799  totalTests++;
800  }
801  }
802 }
803 
804 bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters, bool thorough)
805 {
806  s_thorough = thorough;
807  unsigned int totalTests = 0, failedTests = 0;
808  TestDataFile(filename, overrideParameters, totalTests, failedTests);
809  cout << dec << "\nTests complete. Total tests = " << totalTests << ". Failed tests = " << failedTests << ".\n";
810  if (failedTests != 0)
811  cout << "SOME TESTS FAILED!\n";
812  return failedTests == 0;
813 }
used to pass byte array input as part of a NameValuePairs object
Definition: algparam.h:30
Base class for all exceptions thrown by Crypto++.
Definition: cryptlib.h:124
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
Filter Wrapper for PK_Verifier.
Definition: filters.h:540
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
void Encode(byte *output, size_t outputLen, Signedness sign=UNSIGNED) const
Encode in big-endian format.
Definition: integer.cpp:3179
virtual void Load(BufferedTransformation &bt)
Loads a key from a BufferedTransformation.
Definition: cryptlib.h:1967
size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
Input a byte for processing on a channel.
Definition: cryptlib.h:1725
virtual bool NeedsPrespecifiedDataLengths() const
if this function returns true, SpecifyDataLengths() must be called before attempting to input data ...
Definition: cryptlib.h:1055
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:1950
Abstract base classes that provide a uniform interface to this library.
Thrown when an unexpected type is encountered.
Definition: cryptlib.h:269
CryptoMaterial & AccessMaterial()
returns a reference to the crypto material used by this object
Definition: cryptlib.h:2098
Some other error occurred not belong to any of the above categories.
Definition: cryptlib.h:142
Classes for automatic resource management.
Filter Wrapper for PK_Signer.
Definition: filters.h:520
STL namespace.
std::string GetValueNames() const
Get a list of value names that can be retrieved.
Definition: cryptlib.h:344
void ProcessString(byte *inoutString, size_t length)
Encrypt or decrypt a string of bytes.
Definition: cryptlib.h:801
size_t MinEncodedSize(Signedness sign=UNSIGNED) const
The minimum number of bytes to encode this integer.
Definition: integer.cpp:3167
Append input to a string object.
Definition: filters.h:724
SecByteBlock is a SecBlock<byte> typedef.
Definition: secblock.h:719
Interface for buffered transformations.
Definition: cryptlib.h:1247
const CryptoMaterial & GetMaterial() const
returns a const reference to the crypto material used by this object
Definition: cryptlib.h:2099
Pointer that overloads operator→
Definition: smartptr.h:39
bool MessageEnd(int propagation=-1, bool blocking=true)
Signals the end of messages to the object.
Definition: cryptlib.h:1326
Classes for an unlimited queue to store bytes.
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:319
int GetIntValueWithDefault(const char *name, int defaultValue) const
Get a named value with type int, with default.
Definition: cryptlib.h:364
Filter Wrapper for HashTransformation.
Definition: filters.h:443
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1268
Filter wrapper for decrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpaddin...
Definition: filters.h:496
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.cpp:41
Filter wrapper for encrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpaddin...
Definition: filters.h:479
virtual void Resynchronize(const byte *iv, int ivLength=-1)
resynchronize with an IV. ivLength=-1 means use IVSize()
Definition: cryptlib.h:592
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:1020
Multiple precision integer with arithmetic operations.
Definition: integer.h:31
proxy for the filter created by PK_Decryptor::CreateDecryptionFilter
Definition: filters.h:715
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:422
const CryptoMaterial & GetMaterial() const
returns a const reference to the crypto material used by this object
Definition: cryptlib.h:2083
const NameValuePairs & g_nullNameValuePairs
An empty set of name-value pairs.
Definition: cryptlib.cpp:79
string-based implementation of Store interface
Definition: filters.h:808
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:386
Redirect input to another BufferedTransformation without owning it.
Definition: filters.h:574
Byte Queue.
Definition: queue.h:20
Implementation of BufferedTransformation&#39;s attachment interface in cryptlib.h.
const char * IV()
ConstByteArrayParameter, also accepts const byte * for backwards compatibility.
Definition: argnames.h:21
Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed...
Definition: filters.h:398
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:827
virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0
Check this object for errors.
CryptoMaterial & AccessMaterial()
returns a reference to the crypto material used by this object
Definition: cryptlib.h:2082
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:25
Interface for hash functions and data processing part of MACs.
Definition: cryptlib.h:858
Interface for crypto material, such as public and private keys, and crypto parameters.
Definition: cryptlib.h:1903
virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params=g_nullNameValuePairs)
Generate a random key or crypto parameters.
Definition: cryptlib.h:2018
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:1258
void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0)
this function only needs to be called if NeedsPrespecifiedDataLengths() returns true ...
Definition: cryptlib.cpp:257
No padding added to a block.
Definition: filters.h:385
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition: cryptlib.cpp:518
Crypto++ library namespace.
const std::string AAD_CHANNEL
Channel for additional authenticated data.
Definition: cryptlib.cpp:63
file-based implementation of Sink interface
Definition: files.h:78
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
Flush buffered input and/or output, with signal propagation.
Definition: filters.cpp:78
virtual unsigned int IVSize() const
Returns length of the IV accepted by this object.
Definition: cryptlib.h:583
Interface for retrieving values given their names.
Definition: cryptlib.h:261