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 SignalUnknownAlgorithmError(const std::string& algType)
59 {
60  OutputTestData(*s_currentTestData);
61  throw Exception(Exception::OTHER_ERROR, "Unknown algorithm " + algType + " during validation test");
62 }
63 
64 static void SignalTestError()
65 {
66  OutputTestData(*s_currentTestData);
67  throw Exception(Exception::OTHER_ERROR, "Unexpected error during validation test");
68 }
69 
70 bool DataExists(const TestData &data, const char *name)
71 {
72  TestData::const_iterator i = data.find(name);
73  return (i != data.end());
74 }
75 
76 const std::string & GetRequiredDatum(const TestData &data, const char *name)
77 {
78  TestData::const_iterator i = data.find(name);
79  if (i == data.end())
80  SignalTestError();
81  return i->second;
82 }
83 
84 void RandomizedTransfer(BufferedTransformation &source, BufferedTransformation &target, bool finish, const std::string &channel=DEFAULT_CHANNEL)
85 {
86  while (source.MaxRetrievable() > (finish ? 0 : 4096))
87  {
88  byte buf[4096+64];
89  size_t start = GlobalRNG().GenerateWord32(0, 63);
90  size_t len = GlobalRNG().GenerateWord32(1, UnsignedMin(4096U, 3*source.MaxRetrievable()/2));
91  len = source.Get(buf+start, len);
92  target.ChannelPut(channel, buf+start, len);
93  }
94 }
95 
96 void PutDecodedDatumInto(const TestData &data, const char *name, BufferedTransformation &target)
97 {
98  std::string s1 = GetRequiredDatum(data, name), s2;
99  ByteQueue q;
100 
101  while (!s1.empty())
102  {
103  while (s1[0] == ' ')
104  {
105  s1 = s1.substr(1);
106  if (s1.empty())
107  goto end; // avoid invalid read if s1 is empty
108  }
109 
110  int repeat = 1;
111  if (s1[0] == 'r')
112  {
113  repeat = atoi(s1.c_str()+1);
114  s1 = s1.substr(s1.find(' ')+1);
115  }
116 
117  s2 = ""; // MSVC 6 doesn't have clear();
118 
119  if (s1[0] == '\"')
120  {
121  s2 = s1.substr(1, s1.find('\"', 1)-1);
122  s1 = s1.substr(s2.length() + 2);
123  }
124  else if (s1.substr(0, 2) == "0x")
125  {
126  StringSource(s1.substr(2, s1.find(' ')), true, new HexDecoder(new StringSink(s2)));
127  s1 = s1.substr(STDMIN(s1.find(' '), s1.length()));
128  }
129  else
130  {
131  StringSource(s1.substr(0, s1.find(' ')), true, new HexDecoder(new StringSink(s2)));
132  s1 = s1.substr(STDMIN(s1.find(' '), s1.length()));
133  }
134 
135  while (repeat--)
136  {
137  q.Put((const byte *)s2.data(), s2.size());
138  RandomizedTransfer(q, target, false);
139  }
140  }
141 
142 end:
143  RandomizedTransfer(q, target, true);
144 }
145 
146 std::string GetDecodedDatum(const TestData &data, const char *name)
147 {
148  std::string s;
149  PutDecodedDatumInto(data, name, StringSink(s).Ref());
150  return s;
151 }
152 
153 std::string GetOptionalDecodedDatum(const TestData &data, const char *name)
154 {
155  std::string s;
156  if (DataExists(data, name))
157  PutDecodedDatumInto(data, name, StringSink(s).Ref());
158  return s;
159 }
160 
162 {
163 public:
164  TestDataNameValuePairs(const TestData &data) : m_data(data) {}
165 
166  virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
167  {
168  TestData::const_iterator i = m_data.find(name);
169  if (i == m_data.end())
170  {
171  if (std::string(name) == Name::DigestSize() && valueType == typeid(int))
172  {
173  i = m_data.find("MAC");
174  if (i == m_data.end())
175  i = m_data.find("Digest");
176  if (i == m_data.end())
177  return false;
178 
179  m_temp.resize(0);
180  PutDecodedDatumInto(m_data, i->first.c_str(), StringSink(m_temp).Ref());
181  *reinterpret_cast<int *>(pValue) = (int)m_temp.size();
182  return true;
183  }
184  else
185  return false;
186  }
187 
188  const std::string &value = i->second;
189 
190  if (valueType == typeid(int))
191  *reinterpret_cast<int *>(pValue) = atoi(value.c_str());
192  else if (valueType == typeid(Integer))
193  *reinterpret_cast<Integer *>(pValue) = Integer((std::string(value) + "h").c_str());
194  else if (valueType == typeid(ConstByteArrayParameter))
195  {
196  m_temp.resize(0);
197  PutDecodedDatumInto(m_data, name, StringSink(m_temp).Ref());
198  reinterpret_cast<ConstByteArrayParameter *>(pValue)->Assign((const byte *)m_temp.data(), m_temp.size(), false);
199  }
200  else
201  throw ValueTypeMismatch(name, typeid(std::string), valueType);
202 
203  return true;
204  }
205 
206 private:
207  const TestData &m_data;
208  mutable std::string m_temp;
209 };
210 
211 void TestKeyPairValidAndConsistent(CryptoMaterial &pub, const CryptoMaterial &priv)
212 {
213  // "!!" converts between bool <-> integral.
214  if (!pub.Validate(GlobalRNG(), 2U+!!s_thorough))
215  SignalTestFailure();
216  if (!priv.Validate(GlobalRNG(), 2U+!!s_thorough))
217  SignalTestFailure();
218 
219  ByteQueue bq1, bq2;
220  pub.Save(bq1);
221  pub.AssignFrom(priv);
222  pub.Save(bq2);
223  if (bq1 != bq2)
224  SignalTestFailure();
225 }
226 
227 void TestSignatureScheme(TestData &v)
228 {
229  std::string name = GetRequiredDatum(v, "Name");
230  std::string test = GetRequiredDatum(v, "Test");
231 
232  member_ptr<PK_Signer> signer(ObjectFactoryRegistry<PK_Signer>::Registry().CreateObject(name.c_str()));
233  member_ptr<PK_Verifier> verifier(ObjectFactoryRegistry<PK_Verifier>::Registry().CreateObject(name.c_str()));
234 
235  TestDataNameValuePairs pairs(v);
236 
237  if (test == "GenerateKey")
238  {
239  signer->AccessPrivateKey().GenerateRandom(GlobalRNG(), pairs);
240  verifier->AccessPublicKey().AssignFrom(signer->AccessPrivateKey());
241  }
242  else
243  {
244  std::string keyFormat = GetRequiredDatum(v, "KeyFormat");
245 
246  if (keyFormat == "DER")
247  verifier->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref());
248  else if (keyFormat == "Component")
249  verifier->AccessMaterial().AssignFrom(pairs);
250 
251  if (test == "Verify" || test == "NotVerify")
252  {
253  VerifierFilter verifierFilter(*verifier, NULL, VerifierFilter::SIGNATURE_AT_BEGIN);
254  PutDecodedDatumInto(v, "Signature", verifierFilter);
255  PutDecodedDatumInto(v, "Message", verifierFilter);
256  verifierFilter.MessageEnd();
257  if (verifierFilter.GetLastResult() == (test == "NotVerify"))
258  SignalTestFailure();
259  return;
260  }
261  else if (test == "PublicKeyValid")
262  {
263  if (!verifier->GetMaterial().Validate(GlobalRNG(), 3))
264  SignalTestFailure();
265  return;
266  }
267 
268  if (keyFormat == "DER")
269  signer->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref());
270  else if (keyFormat == "Component")
271  signer->AccessMaterial().AssignFrom(pairs);
272  }
273 
274  if (test == "GenerateKey" || test == "KeyPairValidAndConsistent")
275  {
276  TestKeyPairValidAndConsistent(verifier->AccessMaterial(), signer->GetMaterial());
277  VerifierFilter verifierFilter(*verifier, NULL, VerifierFilter::THROW_EXCEPTION);
278  verifierFilter.Put((const byte *)"abc", 3);
279  StringSource ss("abc", true, new SignerFilter(GlobalRNG(), *signer, new Redirector(verifierFilter)));
280  }
281  else if (test == "Sign")
282  {
283  SignerFilter f(GlobalRNG(), *signer, new HexEncoder(new FileSink(cout)));
284  StringSource ss(GetDecodedDatum(v, "Message"), true, new Redirector(f));
285  SignalTestFailure();
286  }
287  else if (test == "DeterministicSign")
288  {
289  // This test is specialized for RFC 6979. The RFC is a drop-in replacement
290  // for DSA and ECDSA, and access to the seed or secret is not needed. If
291  // additional determinsitic signatures are added, then the test harness will
292  // likely need to be extended.
293  string signature;
294  SignerFilter f(GlobalRNG(), *signer, new HexEncoder(new StringSink(signature)));
295  StringSource ss(GetDecodedDatum(v, "Message"), true, new Redirector(f));
296  if (GetDecodedDatum(v, "Signature") != signature)
297  SignalTestFailure();
298  return;
299  }
300  else if (test == "RandomSign")
301  {
302  SignalTestError();
303  assert(false); // TODO: implement
304  }
305  else
306  {
307  SignalTestError();
308  assert(false);
309  }
310 }
311 
312 void TestAsymmetricCipher(TestData &v)
313 {
314  std::string name = GetRequiredDatum(v, "Name");
315  std::string test = GetRequiredDatum(v, "Test");
316 
317  member_ptr<PK_Encryptor> encryptor(ObjectFactoryRegistry<PK_Encryptor>::Registry().CreateObject(name.c_str()));
318  member_ptr<PK_Decryptor> decryptor(ObjectFactoryRegistry<PK_Decryptor>::Registry().CreateObject(name.c_str()));
319 
320  std::string keyFormat = GetRequiredDatum(v, "KeyFormat");
321 
322  if (keyFormat == "DER")
323  {
324  decryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PrivateKey")).Ref());
325  encryptor->AccessMaterial().Load(StringStore(GetDecodedDatum(v, "PublicKey")).Ref());
326  }
327  else if (keyFormat == "Component")
328  {
329  TestDataNameValuePairs pairs(v);
330  decryptor->AccessMaterial().AssignFrom(pairs);
331  encryptor->AccessMaterial().AssignFrom(pairs);
332  }
333 
334  if (test == "DecryptMatch")
335  {
336  std::string decrypted, expected = GetDecodedDatum(v, "Plaintext");
337  StringSource ss(GetDecodedDatum(v, "Ciphertext"), true, new PK_DecryptorFilter(GlobalRNG(), *decryptor, new StringSink(decrypted)));
338  if (decrypted != expected)
339  SignalTestFailure();
340  }
341  else if (test == "KeyPairValidAndConsistent")
342  {
343  TestKeyPairValidAndConsistent(encryptor->AccessMaterial(), decryptor->GetMaterial());
344  }
345  else
346  {
347  SignalTestError();
348  assert(false);
349  }
350 }
351 
352 void TestSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
353 {
354  std::string name = GetRequiredDatum(v, "Name");
355  std::string test = GetRequiredDatum(v, "Test");
356 
357  std::string key = GetDecodedDatum(v, "Key");
358  std::string plaintext = GetDecodedDatum(v, "Plaintext");
359 
360  TestDataNameValuePairs testDataPairs(v);
361  CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
362 
363  if (test == "Encrypt" || test == "EncryptXorDigest" || test == "Resync" || test == "EncryptionMCT" || test == "DecryptionMCT")
364  {
365  static member_ptr<SymmetricCipher> encryptor, decryptor;
366  static std::string lastName;
367 
368  if (name != lastName)
369  {
370  encryptor.reset(ObjectFactoryRegistry<SymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
371  decryptor.reset(ObjectFactoryRegistry<SymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
372  lastName = name;
373  }
374 
376  if (pairs.GetValue(Name::IV(), iv) && iv.size() != encryptor->IVSize())
377  SignalTestFailure();
378 
379  if (test == "Resync")
380  {
381  encryptor->Resynchronize(iv.begin(), (int)iv.size());
382  decryptor->Resynchronize(iv.begin(), (int)iv.size());
383  }
384  else
385  {
386  encryptor->SetKey((const byte *)key.data(), key.size(), pairs);
387  decryptor->SetKey((const byte *)key.data(), key.size(), pairs);
388  }
389 
390  int seek = pairs.GetIntValueWithDefault("Seek", 0);
391  if (seek)
392  {
393  encryptor->Seek(seek);
394  decryptor->Seek(seek);
395  }
396 
397  std::string encrypted, xorDigest, ciphertext, ciphertextXorDigest;
398  if (test == "EncryptionMCT" || test == "DecryptionMCT")
399  {
400  SymmetricCipher *cipher = encryptor.get();
401  SecByteBlock buf((byte *)plaintext.data(), plaintext.size()), keybuf((byte *)key.data(), key.size());
402 
403  if (test == "DecryptionMCT")
404  {
405  cipher = decryptor.get();
406  ciphertext = GetDecodedDatum(v, "Ciphertext");
407  buf.Assign((byte *)ciphertext.data(), ciphertext.size());
408  }
409 
410  for (int i=0; i<400; i++)
411  {
412  encrypted.reserve(10000 * plaintext.size());
413  for (int j=0; j<10000; j++)
414  {
415  cipher->ProcessString(buf.begin(), buf.size());
416  encrypted.append((char *)buf.begin(), buf.size());
417  }
418 
419  encrypted.erase(0, encrypted.size() - keybuf.size());
420  xorbuf(keybuf.begin(), (const byte *)encrypted.data(), keybuf.size());
421  cipher->SetKey(keybuf, keybuf.size());
422  }
423  encrypted.assign((char *)buf.begin(), buf.size());
424  ciphertext = GetDecodedDatum(v, test == "EncryptionMCT" ? "Ciphertext" : "Plaintext");
425  if (encrypted != ciphertext)
426  {
427  std::cout << "incorrectly encrypted: ";
428  StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
429  xx.Pump(256); xx.Flush(false);
430  std::cout << "\n";
431  SignalTestFailure();
432  }
433  return;
434  }
435 
437  RandomizedTransfer(StringStore(plaintext).Ref(), encFilter, true);
438  encFilter.MessageEnd();
439  /*{
440  std::string z;
441  encryptor->Seek(seek);
442  StringSource ss(plaintext, false, new StreamTransformationFilter(*encryptor, new StringSink(z), StreamTransformationFilter::NO_PADDING));
443  while (ss.Pump(64)) {}
444  ss.PumpAll();
445  for (int i=0; i<z.length(); i++)
446  assert(encrypted[i] == z[i]);
447  }*/
448  if (test != "EncryptXorDigest")
449  ciphertext = GetDecodedDatum(v, "Ciphertext");
450  else
451  {
452  ciphertextXorDigest = GetDecodedDatum(v, "CiphertextXorDigest");
453  xorDigest.append(encrypted, 0, 64);
454  for (size_t i=64; i<encrypted.size(); i++)
455  xorDigest[i%64] ^= encrypted[i];
456  }
457  if (test != "EncryptXorDigest" ? encrypted != ciphertext : xorDigest != ciphertextXorDigest)
458  {
459  std::cout << "incorrectly encrypted: ";
460  StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
461  xx.Pump(2048); xx.Flush(false);
462  std::cout << "\n";
463  SignalTestFailure();
464  }
465  std::string decrypted;
467  RandomizedTransfer(StringStore(encrypted).Ref(), decFilter, true);
468  decFilter.MessageEnd();
469  if (decrypted != plaintext)
470  {
471  std::cout << "incorrectly decrypted: ";
472  StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
473  xx.Pump(256); xx.Flush(false);
474  std::cout << "\n";
475  SignalTestFailure();
476  }
477  }
478  else
479  {
480  std::cout << "unexpected test name\n";
481  SignalTestError();
482  }
483 }
484 
485 void TestAuthenticatedSymmetricCipher(TestData &v, const NameValuePairs &overrideParameters)
486 {
487  std::string type = GetRequiredDatum(v, "AlgorithmType");
488  std::string name = GetRequiredDatum(v, "Name");
489  std::string test = GetRequiredDatum(v, "Test");
490  std::string key = GetDecodedDatum(v, "Key");
491 
492  std::string plaintext = GetOptionalDecodedDatum(v, "Plaintext");
493  std::string ciphertext = GetOptionalDecodedDatum(v, "Ciphertext");
494  std::string header = GetOptionalDecodedDatum(v, "Header");
495  std::string footer = GetOptionalDecodedDatum(v, "Footer");
496  std::string mac = GetOptionalDecodedDatum(v, "MAC");
497 
498  TestDataNameValuePairs testDataPairs(v);
499  CombinedNameValuePairs pairs(overrideParameters, testDataPairs);
500 
501  if (test == "Encrypt" || test == "EncryptXorDigest" || test == "NotVerify")
502  {
504  asc1.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, ENCRYPTION>::Registry().CreateObject(name.c_str()));
505  asc2.reset(ObjectFactoryRegistry<AuthenticatedSymmetricCipher, DECRYPTION>::Registry().CreateObject(name.c_str()));
506  asc1->SetKey((const byte *)key.data(), key.size(), pairs);
507  asc2->SetKey((const byte *)key.data(), key.size(), pairs);
508 
509  std::string encrypted, decrypted;
510  AuthenticatedEncryptionFilter ef(*asc1, new StringSink(encrypted));
511  bool macAtBegin = !mac.empty() && !GlobalRNG().GenerateBit(); // test both ways randomly
513 
514  if (asc1->NeedsPrespecifiedDataLengths())
515  {
516  asc1->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
517  asc2->SpecifyDataLengths(header.size(), plaintext.size(), footer.size());
518  }
519 
520  StringStore sh(header), sp(plaintext), sc(ciphertext), sf(footer), sm(mac);
521 
522  if (macAtBegin)
523  RandomizedTransfer(sm, df, true);
524  sh.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
525  RandomizedTransfer(sc, df, true);
526  sf.CopyTo(df, LWORD_MAX, AAD_CHANNEL);
527  if (!macAtBegin)
528  RandomizedTransfer(sm, df, true);
529  df.MessageEnd();
530 
531  RandomizedTransfer(sh, ef, true, AAD_CHANNEL);
532  RandomizedTransfer(sp, ef, true);
533  RandomizedTransfer(sf, ef, true, AAD_CHANNEL);
534  ef.MessageEnd();
535 
536  if (test == "Encrypt" && encrypted != ciphertext+mac)
537  {
538  std::cout << "incorrectly encrypted: ";
539  StringSource xx(encrypted, false, new HexEncoder(new FileSink(std::cout)));
540  xx.Pump(2048); xx.Flush(false);
541  std::cout << "\n";
542  SignalTestFailure();
543  }
544  if (test == "Encrypt" && decrypted != plaintext)
545  {
546  std::cout << "incorrectly decrypted: ";
547  StringSource xx(decrypted, false, new HexEncoder(new FileSink(std::cout)));
548  xx.Pump(256); xx.Flush(false);
549  std::cout << "\n";
550  SignalTestFailure();
551  }
552 
553  if (ciphertext.size()+mac.size()-plaintext.size() != asc1->DigestSize())
554  {
555  std::cout << "bad MAC size\n";
556  SignalTestFailure();
557  }
558  if (df.GetLastResult() != (test == "Encrypt"))
559  {
560  std::cout << "MAC incorrectly verified\n";
561  SignalTestFailure();
562  }
563  }
564  else
565  {
566  std::cout << "unexpected test name\n";
567  SignalTestError();
568  }
569 }
570 
571 void TestDigestOrMAC(TestData &v, bool testDigest)
572 {
573  std::string name = GetRequiredDatum(v, "Name");
574  std::string test = GetRequiredDatum(v, "Test");
575  const char *digestName = testDigest ? "Digest" : "MAC";
576 
579  HashTransformation *pHash = NULL;
580 
581  TestDataNameValuePairs pairs(v);
582 
583  if (testDigest)
584  {
585  hash.reset(ObjectFactoryRegistry<HashTransformation>::Registry().CreateObject(name.c_str()));
586  pHash = hash.get();
587  }
588  else
589  {
590  mac.reset(ObjectFactoryRegistry<MessageAuthenticationCode>::Registry().CreateObject(name.c_str()));
591  pHash = mac.get();
592  std::string key = GetDecodedDatum(v, "Key");
593  mac->SetKey((const byte *)key.c_str(), key.size(), pairs);
594  }
595 
596  if (test == "Verify" || test == "VerifyTruncated" || test == "NotVerify")
597  {
598  int digestSize = -1;
599  if (test == "VerifyTruncated")
600  digestSize = pairs.GetIntValueWithDefault(Name::DigestSize(), digestSize);
601  HashVerificationFilter verifierFilter(*pHash, NULL, HashVerificationFilter::HASH_AT_BEGIN, digestSize);
602  PutDecodedDatumInto(v, digestName, verifierFilter);
603  PutDecodedDatumInto(v, "Message", verifierFilter);
604  verifierFilter.MessageEnd();
605  if (verifierFilter.GetLastResult() == (test == "NotVerify"))
606  SignalTestFailure();
607  }
608  else
609  {
610  SignalTestError();
611  assert(false);
612  }
613 }
614 
615 void TestKeyDerivationFunction(TestData &v)
616 {
617  std::string name = GetRequiredDatum(v, "Name");
618  std::string test = GetRequiredDatum(v, "Test");
619 
620  if(test == "Skip") return;
621  assert(test == "Verify");
622 
623  std::string key = GetDecodedDatum(v, "Key");
624  std::string salt = GetDecodedDatum(v, "Salt");
625  std::string info = GetDecodedDatum(v, "Info");
626  std::string derived = GetDecodedDatum(v, "DerivedKey");
627  std::string t = GetDecodedDatum(v, "DerivedKeyLength");
628 
629  TestDataNameValuePairs pairs(v);
630  unsigned int length = pairs.GetIntValueWithDefault(Name::DerivedKeyLength(), (int)derived.size());
631 
633  kdf.reset(ObjectFactoryRegistry<KeyDerivationFunction>::Registry().CreateObject(name.c_str()));
634 
635  std::string calc; calc.resize(length);
636  unsigned int ret = kdf->DeriveKey(reinterpret_cast<byte*>(&calc[0]), calc.size(),
637  reinterpret_cast<const byte*>(key.data()), key.size(),
638  reinterpret_cast<const byte*>(salt.data()), salt.size(),
639  reinterpret_cast<const byte*>(info.data()), info.size());
640 
641  if(calc != derived || ret != length)
642  SignalTestFailure();
643 }
644 
645 bool GetField(std::istream &is, std::string &name, std::string &value)
646 {
647  name.resize(0); // GCC workaround: 2.95.3 doesn't have clear()
648  is >> name;
649 
650  if (name.empty())
651  return false;
652 
653  if (name[name.size()-1] != ':')
654  {
655  char c;
656  is >> skipws >> c;
657  if (c != ':')
658  SignalTestError();
659  }
660  else
661  name.erase(name.size()-1);
662 
663  while (is.peek() == ' ')
664  is.ignore(1);
665 
666  // VC60 workaround: getline bug
667  char buffer[128];
668  value.resize(0); // GCC workaround: 2.95.3 doesn't have clear()
669  bool continueLine, space = false;
670 
671  do
672  {
673  do
674  {
675  is.get(buffer, sizeof(buffer));
676  value += buffer;
677  if (buffer[0] == ' ')
678  space = true;
679  }
680  while (buffer[0] != 0);
681  is.clear();
682  is.ignore();
683 
684  if (!value.empty() && value[value.size()-1] == '\r')
685  value.resize(value.size()-1);
686 
687  if (!value.empty() && value[value.size()-1] == '\\')
688  {
689  value.resize(value.size()-1);
690  continueLine = true;
691  }
692  else
693  continueLine = false;
694 
695  std::string::size_type i = value.find('#');
696  if (i != std::string::npos)
697  value.erase(i);
698  }
699  while (continueLine);
700 
701  // Strip intermediate spaces for some values.
702  if (space && (name == "Modulus" || name == "SubgroupOrder" || name == "SubgroupGenerator" ||
703  name == "PublicElement" || name == "PrivateExponent" || name == "Signature"))
704  {
705  string temp;
706  temp.reserve(value.size());
707 
708  std::string::const_iterator it;
709  for(it = value.begin(); it != value.end(); it++)
710  {
711  if(*it != ' ')
712  temp.push_back(*it);
713  }
714 
715  std::swap(temp, value);
716  }
717 
718  return true;
719 }
720 
721 void OutputPair(const NameValuePairs &v, const char *name)
722 {
723  Integer x;
724  bool b = v.GetValue(name, x);
725  CRYPTOPP_UNUSED(b); assert(b);
726  cout << name << ": \\\n ";
727  x.Encode(HexEncoder(new FileSink(cout), false, 64, "\\\n ").Ref(), x.MinEncodedSize());
728  cout << endl;
729 }
730 
731 void OutputNameValuePairs(const NameValuePairs &v)
732 {
733  std::string names = v.GetValueNames();
734  string::size_type i = 0;
735  while (i < names.size())
736  {
737  string::size_type j = names.find_first_of (';', i);
738 
739  if (j == string::npos)
740  return;
741  else
742  {
743  std::string name = names.substr(i, j-i);
744  if (name.find(':') == string::npos)
745  OutputPair(v, name.c_str());
746  }
747 
748  i = j + 1;
749  }
750 }
751 
752 void TestDataFile(std::string filename, const NameValuePairs &overrideParameters, unsigned int &totalTests, unsigned int &failedTests)
753 {
754  static const std::string dataDirectory(CRYPTOPP_DATA_DIR);
755  if (!dataDirectory.empty())
756  {
757  if(dataDirectory != filename.substr(0, dataDirectory.length()))
758  filename.insert(0, dataDirectory);
759  }
760 
761  std::ifstream file(filename.c_str());
762  if (!file.good())
763  throw Exception(Exception::OTHER_ERROR, "Can not open file " + filename + " for reading");
764  TestData v;
765  s_currentTestData = &v;
766  std::string name, value, lastAlgName;
767 
768  while (file)
769  {
770  while (file.peek() == '#')
771  file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
772 
773  if (file.peek() == '\n' || file.peek() == '\r')
774  v.clear();
775 
776  if (!GetField(file, name, value))
777  break;
778  v[name] = value;
779 
780  if (name == "Test" && (s_thorough || v["SlowTest"] != "1"))
781  {
782  bool failed = true;
783  std::string algType = GetRequiredDatum(v, "AlgorithmType");
784 
785  if (lastAlgName != GetRequiredDatum(v, "Name"))
786  {
787  lastAlgName = GetRequiredDatum(v, "Name");
788  cout << "\nTesting " << algType.c_str() << " algorithm " << lastAlgName.c_str() << ".\n";
789  }
790 
791  try
792  {
793  if (algType == "Signature")
794  TestSignatureScheme(v);
795  else if (algType == "SymmetricCipher")
796  TestSymmetricCipher(v, overrideParameters);
797  else if (algType == "AuthenticatedSymmetricCipher")
798  TestAuthenticatedSymmetricCipher(v, overrideParameters);
799  else if (algType == "AsymmetricCipher")
800  TestAsymmetricCipher(v);
801  else if (algType == "MessageDigest")
802  TestDigestOrMAC(v, true);
803  else if (algType == "MAC")
804  TestDigestOrMAC(v, false);
805  else if (algType == "KDF")
806  TestKeyDerivationFunction(v);
807  else if (algType == "FileList")
808  TestDataFile(GetRequiredDatum(v, "Test"), g_nullNameValuePairs, totalTests, failedTests);
809  else
810  SignalUnknownAlgorithmError(algType);
811  failed = false;
812  }
813  catch (const TestFailure &)
814  {
815  cout << "\nTest failed.\n";
816  }
817  catch (const CryptoPP::Exception &e)
818  {
819  cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
820  }
821  catch (const std::exception &e)
822  {
823  cout << "\nstd::exception caught: " << e.what() << endl;
824  }
825 
826  if (failed)
827  {
828  cout << "Skipping to next test.\n";
829  failedTests++;
830  }
831  else
832  cout << "." << flush;
833 
834  totalTests++;
835  }
836  }
837 }
838 
839 bool RunTestDataFile(const char *filename, const NameValuePairs &overrideParameters, bool thorough)
840 {
841  s_thorough = thorough;
842  unsigned int totalTests = 0, failedTests = 0;
843  TestDataFile((filename ? filename : ""), overrideParameters, totalTests, failedTests);
844  cout << dec << "\nTests complete. Total tests = " << totalTests << ". Failed tests = " << failedTests << "." << endl;
845  if (failedTests != 0)
846  cout << "SOME TESTS FAILED!\n";
847  return failedTests == 0;
848 }
849 
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:166
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:554
Filter wrapper for PK_Verifier.
Definition: filters.h:694
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:3338
size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
Input a byte for processing on a channel.
Definition: cryptlib.h:1858
virtual bool NeedsPrespecifiedDataLengths() const
Determines if data lengths must be specified prior to inputting data.
Definition: cryptlib.h:1148
Converts given data to base 16.
Definition: hex.h:16
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:36
virtual void Save(BufferedTransformation &bt) const
Saves a key to a BufferedTransformation.
Definition: cryptlib.h:2088
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:720
Classes for automatic resource management.
Filter wrapper for PK_Signer.
Definition: filters.h:668
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:869
size_t MinEncodedSize(Signedness sign=UNSIGNED) const
The minimum number of bytes to encode this integer.
Definition: integer.cpp:3326
Combines two sets of NameValuePairs.
Definition: algparam.h:135
SecBlock typedef.
Definition: secblock.h:728
Interface for buffered transformations.
Definition: cryptlib.h:1352
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:535
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1378
Filter wrapper for decrypting with AuthenticatedSymmetricCipher.
Definition: filters.h:624
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.cpp:41
Filter wrapper for encrypting with AuthenticatedSymmetricCipher.
Definition: filters.h:599
virtual void Resynchronize(const byte *iv, int ivLength=-1)
Resynchronize with an IV.
Definition: cryptlib.h:653
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:1099
Multiple precision integer with arithmetic operations.
Definition: integer.h:31
Filter wrapper for PK_Decryptor.
Definition: filters.h:943
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be neagtive and incorrectly promoted.
Definition: misc.h:486
const NameValuePairs & g_nullNameValuePairs
An empty set of name-value pairs.
Definition: cryptlib.cpp:79
String-based implementation of Store interface.
Definition: filters.h:1066
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:450
Redirect input to another BufferedTransformation without owning it.
Definition: filters.h:755
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:476
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:895
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:922
Interface for crypto material, such as public and private keys, and crypto parameters.
Definition: cryptlib.h:2036
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:1368
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:461
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:712
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:634
virtual unsigned int IVSize() const
Returns length of the IV accepted by this object.
Definition: cryptlib.h:631
Interface for retrieving values given their names.
Definition: cryptlib.h:277