Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

963 lines
29 KiB

  1. // test.cpp - written and placed in the public domain by Wei Dai
  2. #define CRYPTOPP_DEFAULT_NO_DLL
  3. #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
  4. #include "dll.h"
  5. #include "aes.h"
  6. #include "cryptlib.h"
  7. #include "filters.h"
  8. #include "md5.h"
  9. #include "ripemd.h"
  10. #include "rng.h"
  11. #include "gzip.h"
  12. #include "default.h"
  13. #include "randpool.h"
  14. #include "ida.h"
  15. #include "base64.h"
  16. #include "socketft.h"
  17. #include "wait.h"
  18. #include "factory.h"
  19. #include "whrlpool.h"
  20. #include "tiger.h"
  21. #include "smartptr.h"
  22. #include "validate.h"
  23. #include "bench.h"
  24. #include <algorithm>
  25. #include <iostream>
  26. #include <sstream>
  27. #include <string>
  28. #include <locale>
  29. #include <time.h>
  30. #ifdef CRYPTOPP_WIN32_AVAILABLE
  31. #include <windows.h>
  32. #endif
  33. #if defined(USE_BERKELEY_STYLE_SOCKETS) && !defined(macintosh)
  34. #include <netinet/in.h>
  35. #include <netinet/tcp.h>
  36. #endif
  37. #if (_MSC_VER >= 1000)
  38. #include <crtdbg.h> // for the debug heap
  39. #endif
  40. #if defined(__MWERKS__) && defined(macintosh)
  41. #include <console.h>
  42. #endif
  43. #ifdef _OPENMP
  44. # include <omp.h>
  45. #endif
  46. #ifdef __BORLANDC__
  47. #pragma comment(lib, "cryptlib_bds.lib")
  48. #pragma comment(lib, "ws2_32.lib")
  49. #endif
  50. // Aggressive stack checking with VS2005 SP1 and above.
  51. #if (CRYPTOPP_MSC_VERSION >= 1410)
  52. # pragma strict_gs_check (on)
  53. #endif
  54. USING_NAMESPACE(CryptoPP)
  55. USING_NAMESPACE(std)
  56. const int MAX_PHRASE_LENGTH=250;
  57. void RegisterFactories();
  58. void PrintSeedAndThreads(const std::string& seed);
  59. void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed);
  60. string RSAEncryptString(const char *pubFilename, const char *seed, const char *message);
  61. string RSADecryptString(const char *privFilename, const char *ciphertext);
  62. void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename);
  63. bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename);
  64. void DigestFile(const char *file);
  65. void HmacFile(const char *hexKey, const char *file);
  66. void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile);
  67. string EncryptString(const char *plaintext, const char *passPhrase);
  68. string DecryptString(const char *ciphertext, const char *passPhrase);
  69. void EncryptFile(const char *in, const char *out, const char *passPhrase);
  70. void DecryptFile(const char *in, const char *out, const char *passPhrase);
  71. void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed);
  72. void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames);
  73. void InformationDisperseFile(int threshold, int nShares, const char *filename);
  74. void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames);
  75. void GzipFile(const char *in, const char *out, int deflate_level);
  76. void GunzipFile(const char *in, const char *out);
  77. void Base64Encode(const char *infile, const char *outfile);
  78. void Base64Decode(const char *infile, const char *outfile);
  79. void HexEncode(const char *infile, const char *outfile);
  80. void HexDecode(const char *infile, const char *outfile);
  81. void ForwardTcpPort(const char *sourcePort, const char *destinationHost, const char *destinationPort);
  82. void FIPS140_SampleApplication();
  83. void FIPS140_GenerateRandomFiles();
  84. bool Validate(int, bool, const char *);
  85. void PrintSeedAndThreads(const std::string& seed);
  86. int (*AdhocTest)(int argc, char *argv[]) = NULL;
  87. RandomNumberGenerator & GlobalRNG()
  88. {
  89. static OFB_Mode<AES>::Encryption s_globalRNG;
  90. return dynamic_cast<RandomNumberGenerator&>(s_globalRNG);
  91. }
  92. int CRYPTOPP_API main(int argc, char *argv[])
  93. {
  94. #ifdef _CRTDBG_LEAK_CHECK_DF
  95. // Turn on leak-checking
  96. int tempflag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
  97. tempflag |= _CRTDBG_LEAK_CHECK_DF;
  98. _CrtSetDbgFlag( tempflag );
  99. #endif
  100. #if defined(__MWERKS__) && defined(macintosh)
  101. argc = ccommand(&argv);
  102. #endif
  103. try
  104. {
  105. RegisterFactories();
  106. // Some editors have problems with the '\0' character when redirecting output.
  107. std::string seed = IntToString(time(NULL));
  108. seed.resize(16, ' ');
  109. OFB_Mode<AES>::Encryption& prng = dynamic_cast<OFB_Mode<AES>::Encryption&>(GlobalRNG());
  110. prng.SetKeyWithIV((byte *)seed.data(), 16, (byte *)seed.data());
  111. std::string command, executableName, macFilename;
  112. if (argc < 2)
  113. command = 'h';
  114. else
  115. command = argv[1];
  116. if (command == "g")
  117. {
  118. char thisSeed[1024], privFilename[128], pubFilename[128];
  119. unsigned int keyLength;
  120. cout << "Key length in bits: ";
  121. cin >> keyLength;
  122. cout << "\nSave private key to file: ";
  123. cin >> privFilename;
  124. cout << "\nSave public key to file: ";
  125. cin >> pubFilename;
  126. cout << "\nRandom Seed: ";
  127. ws(cin);
  128. cin.getline(thisSeed, 1024);
  129. GenerateRSAKey(keyLength, privFilename, pubFilename, thisSeed);
  130. }
  131. else if (command == "rs")
  132. RSASignFile(argv[2], argv[3], argv[4]);
  133. else if (command == "rv")
  134. {
  135. bool verified = RSAVerifyFile(argv[2], argv[3], argv[4]);
  136. cout << (verified ? "valid signature" : "invalid signature") << endl;
  137. }
  138. else if (command == "r")
  139. {
  140. char privFilename[128], pubFilename[128];
  141. char thisSeed[1024], message[1024];
  142. cout << "Private key file: ";
  143. cin >> privFilename;
  144. cout << "\nPublic key file: ";
  145. cin >> pubFilename;
  146. cout << "\nRandom Seed: ";
  147. ws(cin);
  148. cin.getline(thisSeed, 1024);
  149. cout << "\nMessage: ";
  150. cin.getline(message, 1024);
  151. string ciphertext = RSAEncryptString(pubFilename, thisSeed, message);
  152. cout << "\nCiphertext: " << ciphertext << endl;
  153. string decrypted = RSADecryptString(privFilename, ciphertext.c_str());
  154. cout << "\nDecrypted: " << decrypted << endl;
  155. }
  156. else if (command == "mt")
  157. {
  158. MaurerRandomnessTest mt;
  159. FileStore fs(argv[2]);
  160. fs.TransferAllTo(mt);
  161. cout << "Maurer Test Value: " << mt.GetTestValue() << endl;
  162. }
  163. else if (command == "mac_dll")
  164. {
  165. std::string fname(argv[2] ? argv[2] : "");
  166. // sanity check on file size
  167. std::fstream dllFile(fname.c_str(), ios::in | ios::out | ios::binary);
  168. if (!dllFile.good())
  169. {
  170. cerr << "Failed to open file \"" << fname << "\"\n";
  171. return 1;
  172. }
  173. std::ifstream::pos_type fileEnd = dllFile.seekg(0, std::ios_base::end).tellg();
  174. if (fileEnd > 20*1000*1000)
  175. {
  176. cerr << "Input file " << fname << " is too large";
  177. cerr << "(size is " << fileEnd << ").\n";
  178. return 1;
  179. }
  180. // read file into memory
  181. unsigned int fileSize = (unsigned int)fileEnd;
  182. SecByteBlock buf(fileSize);
  183. dllFile.seekg(0, std::ios_base::beg);
  184. dllFile.read((char *)buf.begin(), fileSize);
  185. // find positions of relevant sections in the file, based on version 8 of documentation from http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
  186. word32 coffPos = *(word16 *)(buf+0x3c);
  187. word32 optionalHeaderPos = coffPos + 24;
  188. word16 optionalHeaderMagic = *(word16 *)(buf+optionalHeaderPos);
  189. if (optionalHeaderMagic != 0x10b && optionalHeaderMagic != 0x20b)
  190. {
  191. cerr << "Target file is not a PE32 or PE32+ image.\n";
  192. return 3;
  193. }
  194. word32 checksumPos = optionalHeaderPos + 64;
  195. word32 certificateTableDirectoryPos = optionalHeaderPos + (optionalHeaderMagic == 0x10b ? 128 : 144);
  196. word32 certificateTablePos = *(word32 *)(buf+certificateTableDirectoryPos);
  197. word32 certificateTableSize = *(word32 *)(buf+certificateTableDirectoryPos+4);
  198. if (certificateTableSize != 0)
  199. cerr << "Warning: certificate table (IMAGE_DIRECTORY_ENTRY_SECURITY) of target image is not empty.\n";
  200. // find where to place computed MAC
  201. byte mac[] = CRYPTOPP_DUMMY_DLL_MAC;
  202. byte *found = std::search(buf.begin(), buf.end(), mac+0, mac+sizeof(mac));
  203. if (found == buf.end())
  204. {
  205. cerr << "MAC placeholder not found. The MAC may already be placed.\n";
  206. return 2;
  207. }
  208. word32 macPos = (unsigned int)(found-buf.begin());
  209. // compute MAC
  210. member_ptr<MessageAuthenticationCode> pMac(NewIntegrityCheckingMAC());
  211. assert(pMac->DigestSize() == sizeof(mac));
  212. MeterFilter f(new HashFilter(*pMac, new ArraySink(mac, sizeof(mac))));
  213. f.AddRangeToSkip(0, checksumPos, 4);
  214. f.AddRangeToSkip(0, certificateTableDirectoryPos, 8);
  215. f.AddRangeToSkip(0, macPos, sizeof(mac));
  216. f.AddRangeToSkip(0, certificateTablePos, certificateTableSize);
  217. f.PutMessageEnd(buf.begin(), buf.size());
  218. // place MAC
  219. cout << "Placing MAC in file " << fname << ", location " << macPos;
  220. cout << " (0x" << std::hex << macPos << std::dec << ").\n";
  221. dllFile.seekg(macPos, std::ios_base::beg);
  222. dllFile.write((char *)mac, sizeof(mac));
  223. }
  224. else if (command == "m")
  225. DigestFile(argv[2]);
  226. else if (command == "tv")
  227. {
  228. std::string fname = (argv[2] ? argv[2] : "all");
  229. if (fname.find(".txt") == std::string::npos)
  230. fname = "TestVectors/" + fname + ".txt";
  231. PrintSeedAndThreads(seed);
  232. return !RunTestDataFile(fname.c_str());
  233. }
  234. else if (command == "t")
  235. {
  236. // VC60 workaround: use char array instead of std::string to workaround MSVC's getline bug
  237. char passPhrase[MAX_PHRASE_LENGTH], plaintext[1024];
  238. cout << "Passphrase: ";
  239. cin.getline(passPhrase, MAX_PHRASE_LENGTH);
  240. cout << "\nPlaintext: ";
  241. cin.getline(plaintext, 1024);
  242. string ciphertext = EncryptString(plaintext, passPhrase);
  243. cout << "\nCiphertext: " << ciphertext << endl;
  244. string decrypted = DecryptString(ciphertext.c_str(), passPhrase);
  245. cout << "\nDecrypted: " << decrypted << endl;
  246. return 0;
  247. }
  248. else if (command == "e64")
  249. Base64Encode(argv[2], argv[3]);
  250. else if (command == "d64")
  251. Base64Decode(argv[2], argv[3]);
  252. else if (command == "e16")
  253. HexEncode(argv[2], argv[3]);
  254. else if (command == "d16")
  255. HexDecode(argv[2], argv[3]);
  256. else if (command == "e" || command == "d")
  257. {
  258. char passPhrase[MAX_PHRASE_LENGTH];
  259. cout << "Passphrase: ";
  260. cin.getline(passPhrase, MAX_PHRASE_LENGTH);
  261. if (command == "e")
  262. EncryptFile(argv[2], argv[3], passPhrase);
  263. else
  264. DecryptFile(argv[2], argv[3], passPhrase);
  265. }
  266. else if (command == "ss")
  267. {
  268. char thisSeed[1024];
  269. cout << "\nRandom Seed: ";
  270. ws(cin);
  271. cin.getline(thisSeed, 1024);
  272. SecretShareFile(StringToValue<int, true>(argv[2]), StringToValue<int, true>(argv[3]), argv[4], thisSeed);
  273. }
  274. else if (command == "sr")
  275. SecretRecoverFile(argc-3, argv[2], argv+3);
  276. else if (command == "id")
  277. InformationDisperseFile(StringToValue<int, true>(argv[2]), StringToValue<int, true>(argv[3]), argv[4]);
  278. else if (command == "ir")
  279. InformationRecoverFile(argc-3, argv[2], argv+3);
  280. else if (command == "v" || command == "vv")
  281. return !Validate(argc>2 ? StringToValue<int, true>(argv[2]) : 0, argv[1][1] == 'v', argc>3 ? argv[3] : NULL);
  282. else if (command == "b")
  283. BenchmarkAll(argc<3 ? 1 : StringToValue<float, true>(argv[2]), argc<4 ? 0 : StringToValue<float, true>(argv[3])*1e9);
  284. else if (command == "b2")
  285. BenchmarkAll2(argc<3 ? 1 : StringToValue<float, true>(argv[2]), argc<4 ? 0 : StringToValue<float, true>(argv[3])*1e9);
  286. else if (command == "z")
  287. GzipFile(argv[3], argv[4], argv[2][0]-'0');
  288. else if (command == "u")
  289. GunzipFile(argv[2], argv[3]);
  290. else if (command == "fips")
  291. FIPS140_SampleApplication();
  292. else if (command == "fips-rand")
  293. FIPS140_GenerateRandomFiles();
  294. else if (command == "ft")
  295. ForwardTcpPort(argv[2], argv[3], argv[4]);
  296. else if (command == "a")
  297. {
  298. if (AdhocTest)
  299. return (*AdhocTest)(argc, argv);
  300. else
  301. {
  302. cerr << "AdhocTest not defined.\n";
  303. return 1;
  304. }
  305. }
  306. else if (command == "hmac")
  307. HmacFile(argv[2], argv[3]);
  308. else if (command == "ae")
  309. AES_CTR_Encrypt(argv[2], argv[3], argv[4], argv[5]);
  310. else if (command == "h")
  311. {
  312. FileSource usage("TestData/usage.dat", true, new FileSink(cout));
  313. return 1;
  314. }
  315. else if (command == "V")
  316. {
  317. cout << CRYPTOPP_VERSION / 100 << '.' << (CRYPTOPP_VERSION % 100) / 10 << '.' << CRYPTOPP_VERSION % 10 << endl;
  318. }
  319. else
  320. {
  321. cerr << "Unrecognized command. Run \"cryptest h\" to obtain usage information.\n";
  322. return 1;
  323. }
  324. return 0;
  325. }
  326. catch(const CryptoPP::Exception &e)
  327. {
  328. cout << "\nCryptoPP::Exception caught: " << e.what() << endl;
  329. return -1;
  330. }
  331. catch(const std::exception &e)
  332. {
  333. cout << "\nstd::exception caught: " << e.what() << endl;
  334. return -2;
  335. }
  336. } // End main()
  337. void FIPS140_GenerateRandomFiles()
  338. {
  339. #ifdef OS_RNG_AVAILABLE
  340. DefaultAutoSeededRNG rng;
  341. RandomNumberStore store(rng, ULONG_MAX);
  342. for (unsigned int i=0; i<100000; i++)
  343. store.TransferTo(FileSink((IntToString(i) + ".rnd").c_str()).Ref(), 20000);
  344. #else
  345. cout << "OS provided RNG not available.\n";
  346. exit(-1);
  347. #endif
  348. }
  349. template <class T, bool NON_NEGATIVE>
  350. T StringToValue(const std::string& str) {
  351. std::istringstream iss(str);
  352. T value;
  353. iss >> value;
  354. // Use fail(), not bad()
  355. if (iss.fail())
  356. throw InvalidArgument("cryptest.exe: '" + str +"' is not a value");
  357. #if NON_NEGATIVE
  358. if (value < 0)
  359. throw InvalidArgument("cryptest.exe: '" + str +"' is negative");
  360. #endif
  361. return value;
  362. }
  363. template<>
  364. int StringToValue<int, true>(const std::string& str)
  365. {
  366. Integer n(str.c_str());
  367. long l = n.ConvertToLong();
  368. int r;
  369. if(!SafeConvert(l, r))
  370. throw InvalidArgument("cryptest.exe: '" + str +"' is not an integer value");
  371. return r;
  372. }
  373. void PrintSeedAndThreads(const std::string& seed)
  374. {
  375. cout << "Using seed: " << seed << endl;
  376. #ifdef _OPENMP
  377. int tc = 0;
  378. #pragma omp parallel
  379. {
  380. tc = omp_get_num_threads();
  381. }
  382. std::cout << "Using " << tc << " OMP " << (tc == 1 ? "thread" : "threads") << std::endl;
  383. #endif
  384. }
  385. SecByteBlock HexDecodeString(const char *hex)
  386. {
  387. StringSource ss(hex, true, new HexDecoder);
  388. SecByteBlock result((size_t)ss.MaxRetrievable());
  389. ss.Get(result, result.size());
  390. return result;
  391. }
  392. void GenerateRSAKey(unsigned int keyLength, const char *privFilename, const char *pubFilename, const char *seed)
  393. {
  394. RandomPool randPool;
  395. randPool.IncorporateEntropy((byte *)seed, strlen(seed));
  396. RSAES_OAEP_SHA_Decryptor priv(randPool, keyLength);
  397. HexEncoder privFile(new FileSink(privFilename));
  398. priv.DEREncode(privFile);
  399. privFile.MessageEnd();
  400. RSAES_OAEP_SHA_Encryptor pub(priv);
  401. HexEncoder pubFile(new FileSink(pubFilename));
  402. pub.DEREncode(pubFile);
  403. pubFile.MessageEnd();
  404. }
  405. string RSAEncryptString(const char *pubFilename, const char *seed, const char *message)
  406. {
  407. FileSource pubFile(pubFilename, true, new HexDecoder);
  408. RSAES_OAEP_SHA_Encryptor pub(pubFile);
  409. RandomPool randPool;
  410. randPool.IncorporateEntropy((byte *)seed, strlen(seed));
  411. string result;
  412. StringSource(message, true, new PK_EncryptorFilter(randPool, pub, new HexEncoder(new StringSink(result))));
  413. return result;
  414. }
  415. string RSADecryptString(const char *privFilename, const char *ciphertext)
  416. {
  417. FileSource privFile(privFilename, true, new HexDecoder);
  418. RSAES_OAEP_SHA_Decryptor priv(privFile);
  419. string result;
  420. StringSource(ciphertext, true, new HexDecoder(new PK_DecryptorFilter(GlobalRNG(), priv, new StringSink(result))));
  421. return result;
  422. }
  423. void RSASignFile(const char *privFilename, const char *messageFilename, const char *signatureFilename)
  424. {
  425. FileSource privFile(privFilename, true, new HexDecoder);
  426. RSASS<PKCS1v15, SHA>::Signer priv(privFile);
  427. FileSource f(messageFilename, true, new SignerFilter(GlobalRNG(), priv, new HexEncoder(new FileSink(signatureFilename))));
  428. }
  429. bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename)
  430. {
  431. FileSource pubFile(pubFilename, true, new HexDecoder);
  432. RSASS<PKCS1v15, SHA>::Verifier pub(pubFile);
  433. FileSource signatureFile(signatureFilename, true, new HexDecoder);
  434. if (signatureFile.MaxRetrievable() != pub.SignatureLength())
  435. return false;
  436. SecByteBlock signature(pub.SignatureLength());
  437. signatureFile.Get(signature, signature.size());
  438. VerifierFilter *verifierFilter = new VerifierFilter(pub);
  439. verifierFilter->Put(signature, pub.SignatureLength());
  440. FileSource f(messageFilename, true, verifierFilter);
  441. return verifierFilter->GetLastResult();
  442. }
  443. void DigestFile(const char *filename)
  444. {
  445. SHA1 sha;
  446. RIPEMD160 ripemd;
  447. SHA256 sha256;
  448. Tiger tiger;
  449. SHA512 sha512;
  450. Whirlpool whirlpool;
  451. vector_member_ptrs<HashFilter> filters(6);
  452. filters[0].reset(new HashFilter(sha));
  453. filters[1].reset(new HashFilter(ripemd));
  454. filters[2].reset(new HashFilter(tiger));
  455. filters[3].reset(new HashFilter(sha256));
  456. filters[4].reset(new HashFilter(sha512));
  457. filters[5].reset(new HashFilter(whirlpool));
  458. member_ptr<ChannelSwitch> channelSwitch(new ChannelSwitch);
  459. size_t i;
  460. for (i=0; i<filters.size(); i++)
  461. channelSwitch->AddDefaultRoute(*filters[i]);
  462. FileSource(filename, true, channelSwitch.release());
  463. HexEncoder encoder(new FileSink(cout), false);
  464. for (i=0; i<filters.size(); i++)
  465. {
  466. cout << filters[i]->AlgorithmName() << ": ";
  467. filters[i]->TransferTo(encoder);
  468. cout << "\n";
  469. }
  470. }
  471. void HmacFile(const char *hexKey, const char *file)
  472. {
  473. member_ptr<MessageAuthenticationCode> mac;
  474. if (strcmp(hexKey, "selftest") == 0)
  475. {
  476. cerr << "Computing HMAC/SHA1 value for self test.\n";
  477. mac.reset(NewIntegrityCheckingMAC());
  478. }
  479. else
  480. {
  481. std::string decodedKey;
  482. StringSource(hexKey, true, new HexDecoder(new StringSink(decodedKey)));
  483. mac.reset(new HMAC<SHA1>((const byte *)decodedKey.data(), decodedKey.size()));
  484. }
  485. FileSource(file, true, new HashFilter(*mac, new HexEncoder(new FileSink(cout))));
  486. }
  487. void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile)
  488. {
  489. SecByteBlock key = HexDecodeString(hexKey);
  490. SecByteBlock iv = HexDecodeString(hexIV);
  491. CTR_Mode<AES>::Encryption aes(key, key.size(), iv);
  492. FileSource(infile, true, new StreamTransformationFilter(aes, new FileSink(outfile)));
  493. }
  494. string EncryptString(const char *instr, const char *passPhrase)
  495. {
  496. string outstr;
  497. DefaultEncryptorWithMAC encryptor(passPhrase, new HexEncoder(new StringSink(outstr)));
  498. encryptor.Put((byte *)instr, strlen(instr));
  499. encryptor.MessageEnd();
  500. return outstr;
  501. }
  502. string DecryptString(const char *instr, const char *passPhrase)
  503. {
  504. string outstr;
  505. HexDecoder decryptor(new DefaultDecryptorWithMAC(passPhrase, new StringSink(outstr)));
  506. decryptor.Put((byte *)instr, strlen(instr));
  507. decryptor.MessageEnd();
  508. return outstr;
  509. }
  510. void EncryptFile(const char *in, const char *out, const char *passPhrase)
  511. {
  512. FileSource f(in, true, new DefaultEncryptorWithMAC(passPhrase, new FileSink(out)));
  513. }
  514. void DecryptFile(const char *in, const char *out, const char *passPhrase)
  515. {
  516. FileSource f(in, true, new DefaultDecryptorWithMAC(passPhrase, new FileSink(out)));
  517. }
  518. void SecretShareFile(int threshold, int nShares, const char *filename, const char *seed)
  519. {
  520. assert(nShares >= 1 && nShares<=1000);
  521. if (nShares < 1 || nShares > 1000)
  522. throw InvalidArgument("SecretShareFile: " + IntToString(nShares) + " is not in range [1, 1000]");
  523. RandomPool rng;
  524. rng.IncorporateEntropy((byte *)seed, strlen(seed));
  525. ChannelSwitch *channelSwitch;
  526. FileSource source(filename, false, new SecretSharing(rng, threshold, nShares, channelSwitch = new ChannelSwitch));
  527. vector_member_ptrs<FileSink> fileSinks(nShares);
  528. string channel;
  529. for (int i=0; i<nShares; i++)
  530. {
  531. char extension[5] = ".000";
  532. extension[1]='0'+byte(i/100);
  533. extension[2]='0'+byte((i/10)%10);
  534. extension[3]='0'+byte(i%10);
  535. fileSinks[i].reset(new FileSink((string(filename)+extension).c_str()));
  536. channel = WordToString<word32>(i);
  537. fileSinks[i]->Put((const byte *)channel.data(), 4);
  538. channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL);
  539. }
  540. source.PumpAll();
  541. }
  542. void SecretRecoverFile(int threshold, const char *outFilename, char *const *inFilenames)
  543. {
  544. assert(threshold >= 1 && threshold <=1000);
  545. if (threshold < 1 || threshold > 1000)
  546. throw InvalidArgument("SecretRecoverFile: " + IntToString(threshold) + " is not in range [1, 1000]");
  547. SecretRecovery recovery(threshold, new FileSink(outFilename));
  548. vector_member_ptrs<FileSource> fileSources(threshold);
  549. SecByteBlock channel(4);
  550. int i;
  551. for (i=0; i<threshold; i++)
  552. {
  553. fileSources[i].reset(new FileSource(inFilenames[i], false));
  554. fileSources[i]->Pump(4);
  555. fileSources[i]->Get(channel, 4);
  556. fileSources[i]->Attach(new ChannelSwitch(recovery, string((char *)channel.begin(), 4)));
  557. }
  558. while (fileSources[0]->Pump(256))
  559. for (i=1; i<threshold; i++)
  560. fileSources[i]->Pump(256);
  561. for (i=0; i<threshold; i++)
  562. fileSources[i]->PumpAll();
  563. }
  564. void InformationDisperseFile(int threshold, int nShares, const char *filename)
  565. {
  566. assert(threshold >= 1 && threshold <=1000);
  567. if (threshold < 1 || threshold > 1000)
  568. throw InvalidArgument("InformationDisperseFile: " + IntToString(nShares) + " is not in range [1, 1000]");
  569. ChannelSwitch *channelSwitch;
  570. FileSource source(filename, false, new InformationDispersal(threshold, nShares, channelSwitch = new ChannelSwitch));
  571. vector_member_ptrs<FileSink> fileSinks(nShares);
  572. string channel;
  573. for (int i=0; i<nShares; i++)
  574. {
  575. char extension[5] = ".000";
  576. extension[1]='0'+byte(i/100);
  577. extension[2]='0'+byte((i/10)%10);
  578. extension[3]='0'+byte(i%10);
  579. fileSinks[i].reset(new FileSink((string(filename)+extension).c_str()));
  580. channel = WordToString<word32>(i);
  581. fileSinks[i]->Put((const byte *)channel.data(), 4);
  582. channelSwitch->AddRoute(channel, *fileSinks[i], DEFAULT_CHANNEL);
  583. }
  584. source.PumpAll();
  585. }
  586. void InformationRecoverFile(int threshold, const char *outFilename, char *const *inFilenames)
  587. {
  588. assert(threshold<=1000);
  589. if (threshold < 1 || threshold > 1000)
  590. throw InvalidArgument("InformationRecoverFile: " + IntToString(threshold) + " is not in range [1, 1000]");
  591. InformationRecovery recovery(threshold, new FileSink(outFilename));
  592. vector_member_ptrs<FileSource> fileSources(threshold);
  593. SecByteBlock channel(4);
  594. int i;
  595. for (i=0; i<threshold; i++)
  596. {
  597. fileSources[i].reset(new FileSource(inFilenames[i], false));
  598. fileSources[i]->Pump(4);
  599. fileSources[i]->Get(channel, 4);
  600. fileSources[i]->Attach(new ChannelSwitch(recovery, string((char *)channel.begin(), 4)));
  601. }
  602. while (fileSources[0]->Pump(256))
  603. for (i=1; i<threshold; i++)
  604. fileSources[i]->Pump(256);
  605. for (i=0; i<threshold; i++)
  606. fileSources[i]->PumpAll();
  607. }
  608. void GzipFile(const char *in, const char *out, int deflate_level)
  609. {
  610. // FileSource(in, true, new Gzip(new FileSink(out), deflate_level));
  611. // use a filter graph to compare decompressed data with original
  612. //
  613. // Source ----> Gzip ------> Sink
  614. // \ |
  615. // \ Gunzip
  616. // \ |
  617. // \ v
  618. // > ComparisonFilter
  619. EqualityComparisonFilter comparison;
  620. Gunzip gunzip(new ChannelSwitch(comparison, "0"));
  621. gunzip.SetAutoSignalPropagation(0);
  622. FileSink sink(out);
  623. ChannelSwitch *cs;
  624. Gzip gzip(cs = new ChannelSwitch(sink), deflate_level);
  625. cs->AddDefaultRoute(gunzip);
  626. cs = new ChannelSwitch(gzip);
  627. cs->AddDefaultRoute(comparison, "1");
  628. FileSource source(in, true, cs);
  629. comparison.ChannelMessageSeriesEnd("0");
  630. comparison.ChannelMessageSeriesEnd("1");
  631. }
  632. void GunzipFile(const char *in, const char *out)
  633. {
  634. FileSource(in, true, new Gunzip(new FileSink(out)));
  635. }
  636. void Base64Encode(const char *in, const char *out)
  637. {
  638. FileSource(in, true, new Base64Encoder(new FileSink(out)));
  639. }
  640. void Base64Decode(const char *in, const char *out)
  641. {
  642. FileSource(in, true, new Base64Decoder(new FileSink(out)));
  643. }
  644. void HexEncode(const char *in, const char *out)
  645. {
  646. FileSource(in, true, new HexEncoder(new FileSink(out)));
  647. }
  648. void HexDecode(const char *in, const char *out)
  649. {
  650. FileSource(in, true, new HexDecoder(new FileSink(out)));
  651. }
  652. void ForwardTcpPort(const char *sourcePortName, const char *destinationHost, const char *destinationPortName)
  653. {
  654. #ifdef SOCKETS_AVAILABLE
  655. SocketsInitializer sockInit;
  656. Socket sockListen, sockSource, sockDestination;
  657. int sourcePort = Socket::PortNameToNumber(sourcePortName);
  658. int destinationPort = Socket::PortNameToNumber(destinationPortName);
  659. sockListen.Create();
  660. sockListen.Bind(sourcePort);
  661. int err = setsockopt(sockListen, IPPROTO_TCP, TCP_NODELAY, "\x01", 1);
  662. assert(err == 0);
  663. if(err != 0)
  664. throw Socket::Err(sockListen, "setsockopt", sockListen.GetLastError());
  665. cout << "Listing on port " << sourcePort << ".\n";
  666. sockListen.Listen();
  667. sockListen.Accept(sockSource);
  668. cout << "Connection accepted on port " << sourcePort << ".\n";
  669. sockListen.CloseSocket();
  670. cout << "Making connection to " << destinationHost << ", port " << destinationPort << ".\n";
  671. sockDestination.Create();
  672. sockDestination.Connect(destinationHost, destinationPort);
  673. cout << "Connection made to " << destinationHost << ", starting to forward.\n";
  674. SocketSource out(sockSource, false, new SocketSink(sockDestination));
  675. SocketSource in(sockDestination, false, new SocketSink(sockSource));
  676. WaitObjectContainer waitObjects;
  677. while (!(in.SourceExhausted() && out.SourceExhausted()))
  678. {
  679. waitObjects.Clear();
  680. out.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - out", NULL));
  681. in.GetWaitObjects(waitObjects, CallStack("ForwardTcpPort - in", NULL));
  682. waitObjects.Wait(INFINITE_TIME);
  683. if (!out.SourceExhausted())
  684. {
  685. cout << "o" << flush;
  686. out.PumpAll2(false);
  687. if (out.SourceExhausted())
  688. cout << "EOF received on source socket.\n";
  689. }
  690. if (!in.SourceExhausted())
  691. {
  692. cout << "i" << flush;
  693. in.PumpAll2(false);
  694. if (in.SourceExhausted())
  695. cout << "EOF received on destination socket.\n";
  696. }
  697. }
  698. #else
  699. cout << "Socket support was not enabled at compile time.\n";
  700. exit(-1);
  701. #endif
  702. }
  703. bool Validate(int alg, bool thorough, const char *seedInput)
  704. {
  705. bool result;
  706. // Some editors have problems with the '\0' character when redirecting output.
  707. // seedInput is argv[3] when issuing 'cryptest.exe v all <seed>'
  708. std::string seed = (seedInput ? seedInput : IntToString(time(NULL)));
  709. seed.resize(16, ' ');
  710. OFB_Mode<AES>::Encryption& prng = dynamic_cast<OFB_Mode<AES>::Encryption&>(GlobalRNG());
  711. prng.SetKeyWithIV((byte *)seed.data(), 16, (byte *)seed.data());
  712. PrintSeedAndThreads(seed);
  713. switch (alg)
  714. {
  715. case 0: result = ValidateAll(thorough); break;
  716. case 1: result = TestSettings(); break;
  717. case 2: result = TestOS_RNG(); break;
  718. case 3: result = ValidateMD5(); break;
  719. case 4: result = ValidateSHA(); break;
  720. case 5: result = ValidateDES(); break;
  721. case 6: result = ValidateIDEA(); break;
  722. case 7: result = ValidateARC4(); break;
  723. case 8: result = ValidateRC5(); break;
  724. case 9: result = ValidateBlowfish(); break;
  725. // case 10: result = ValidateDiamond2(); break;
  726. case 11: result = ValidateThreeWay(); break;
  727. case 12: result = ValidateBBS(); break;
  728. case 13: result = ValidateDH(); break;
  729. case 14: result = ValidateRSA(); break;
  730. case 15: result = ValidateElGamal(); break;
  731. case 16: result = ValidateDSA(thorough); break;
  732. // case 17: result = ValidateHAVAL(); break;
  733. case 18: result = ValidateSAFER(); break;
  734. case 19: result = ValidateLUC(); break;
  735. case 20: result = ValidateRabin(); break;
  736. // case 21: result = ValidateBlumGoldwasser(); break;
  737. case 22: result = ValidateECP(); break;
  738. case 23: result = ValidateEC2N(); break;
  739. // case 24: result = ValidateMD5MAC(); break;
  740. case 25: result = ValidateGOST(); break;
  741. case 26: result = ValidateTiger(); break;
  742. case 27: result = ValidateRIPEMD(); break;
  743. case 28: result = ValidateHMAC(); break;
  744. // case 29: result = ValidateXMACC(); break;
  745. case 30: result = ValidateSHARK(); break;
  746. case 32: result = ValidateLUC_DH(); break;
  747. case 33: result = ValidateLUC_DL(); break;
  748. case 34: result = ValidateSEAL(); break;
  749. case 35: result = ValidateCAST(); break;
  750. case 36: result = ValidateSquare(); break;
  751. case 37: result = ValidateRC2(); break;
  752. case 38: result = ValidateRC6(); break;
  753. case 39: result = ValidateMARS(); break;
  754. case 40: result = ValidateRW(); break;
  755. case 41: result = ValidateMD2(); break;
  756. case 42: result = ValidateNR(); break;
  757. case 43: result = ValidateMQV(); break;
  758. case 44: result = ValidateRijndael(); break;
  759. case 45: result = ValidateTwofish(); break;
  760. case 46: result = ValidateSerpent(); break;
  761. case 47: result = ValidateCipherModes(); break;
  762. case 48: result = ValidateCRC32(); break;
  763. case 49: result = ValidateECDSA(); break;
  764. case 50: result = ValidateXTR_DH(); break;
  765. case 51: result = ValidateSKIPJACK(); break;
  766. case 52: result = ValidateSHA2(); break;
  767. case 53: result = ValidatePanama(); break;
  768. case 54: result = ValidateAdler32(); break;
  769. case 55: result = ValidateMD4(); break;
  770. case 56: result = ValidatePBKDF(); break;
  771. case 57: result = ValidateESIGN(); break;
  772. case 58: result = ValidateDLIES(); break;
  773. case 59: result = ValidateBaseCode(); break;
  774. case 60: result = ValidateSHACAL2(); break;
  775. case 61: result = ValidateCamellia(); break;
  776. case 62: result = ValidateWhirlpool(); break;
  777. case 63: result = ValidateTTMAC(); break;
  778. case 64: result = ValidateSalsa(); break;
  779. case 65: result = ValidateSosemanuk(); break;
  780. case 66: result = ValidateVMAC(); break;
  781. case 67: result = ValidateCCM(); break;
  782. case 68: result = ValidateGCM(); break;
  783. case 69: result = ValidateCMAC(); break;
  784. case 70: result = ValidateHKDF(); break;
  785. default: return false;
  786. }
  787. // Safer functions on Windows for C&A, https://github.com/weidai11/cryptopp/issues/55
  788. #if (CRYPTOPP_MSC_VERSION >= 1400)
  789. tm localTime = {};
  790. char timeBuf[64];
  791. errno_t err;
  792. const time_t endTime = time(NULL);
  793. err = localtime_s(&localTime, &endTime);
  794. assert(err == 0);
  795. err = asctime_s(timeBuf, sizeof(timeBuf), &localTime);
  796. assert(err == 0);
  797. cout << "\nTest ended at " << timeBuf;
  798. #else
  799. const time_t endTime = time(NULL);
  800. cout << "\nTest ended at " << asctime(localtime(&endTime));
  801. #endif
  802. cout << "Seed used was: " << seed << endl;
  803. return result;
  804. }