00001
00002
00003 #define _CRT_SECURE_NO_DEPRECATE
00004
00005 #include "bench.h"
00006 #include "crc.h"
00007 #include "adler32.h"
00008 #include "idea.h"
00009 #include "des.h"
00010 #include "rc5.h"
00011 #include "blowfish.h"
00012 #include "wake.h"
00013 #include "cast.h"
00014 #include "seal.h"
00015 #include "rc6.h"
00016 #include "mars.h"
00017 #include "twofish.h"
00018 #include "serpent.h"
00019 #include "skipjack.h"
00020 #include "cbcmac.h"
00021 #include "dmac.h"
00022 #include "aes.h"
00023 #include "blumshub.h"
00024 #include "rng.h"
00025 #include "files.h"
00026 #include "hex.h"
00027 #include "modes.h"
00028 #include "factory.h"
00029
00030 #include <time.h>
00031 #include <math.h>
00032 #include <iostream>
00033 #include <iomanip>
00034
00035 USING_NAMESPACE(CryptoPP)
00036 USING_NAMESPACE(std)
00037
00038 #ifdef CLOCKS_PER_SEC
00039 const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC;
00040 #elif defined(CLK_TCK)
00041 const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK;
00042 #else
00043 const double CLOCK_TICKS_PER_SECOND = 1000000.0;
00044 #endif
00045
00046 double logtotal = 0, g_allocatedTime, g_hertz;
00047 unsigned int logcount = 0;
00048
00049 static const byte *const key=(byte *)"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
00050
00051 void OutputResultBytes(const char *name, double length, double timeTaken)
00052 {
00053 double mbs = length / timeTaken / (1024*1024);
00054 cout << "\n<TR><TH>" << name;
00055
00056 cout << setiosflags(ios::fixed);
00057
00058 cout << "<TD>" << setprecision(0) << setiosflags(ios::fixed) << mbs;
00059 if (g_hertz)
00060 cout << "<TD>" << setprecision(1) << setiosflags(ios::fixed) << timeTaken * g_hertz / length;
00061 cout << resetiosflags(ios::fixed);
00062 logtotal += log(mbs);
00063 logcount++;
00064 }
00065
00066 void OutputResultKeying(double iterations, double timeTaken)
00067 {
00068 cout << "<TD>" << setprecision(3) << setiosflags(ios::fixed) << (1000*1000*timeTaken/iterations);
00069 if (g_hertz)
00070 cout << "<TD>" << setprecision(0) << setiosflags(ios::fixed) << timeTaken * g_hertz / iterations;
00071 }
00072
00073 void OutputResultOperations(const char *name, const char *operation, bool pc, unsigned long iterations, double timeTaken)
00074 {
00075 cout << "\n<TR><TH>" << name << " " << operation << (pc ? " with precomputation" : "");
00076
00077
00078
00079 cout << "<TD>" << setprecision(2) << setiosflags(ios::fixed) << (1000*timeTaken/iterations);
00080 if (g_hertz)
00081 cout << "<TD>" << setprecision(2) << setiosflags(ios::fixed) << timeTaken * g_hertz / iterations / 1000000;
00082 cout << resetiosflags(ios::fixed);
00083
00084 logtotal += log(iterations/timeTaken);
00085 logcount++;
00086 }
00087
00088 void BenchMark(const char *name, BlockTransformation &cipher, double timeTotal)
00089 {
00090 const int BUF_SIZE = RoundUpToMultipleOf(2048U, cipher.OptimalNumberOfParallelBlocks() * cipher.BlockSize());
00091 AlignedSecByteBlock buf(BUF_SIZE);
00092 const int nBlocks = BUF_SIZE / cipher.BlockSize();
00093 clock_t start = clock();
00094
00095 unsigned long i=0, blocks=1;
00096 double timeTaken;
00097 do
00098 {
00099 blocks *= 2;
00100 for (; i<blocks; i++)
00101 cipher.ProcessAndXorMultipleBlocks(buf, NULL, buf, nBlocks);
00102 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
00103 }
00104 while (timeTaken < 2.0/3*timeTotal);
00105
00106 OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
00107 }
00108
00109 void BenchMark(const char *name, StreamTransformation &cipher, double timeTotal)
00110 {
00111 const int BUF_SIZE=RoundUpToMultipleOf(2048U, cipher.OptimalBlockSize());
00112 AlignedSecByteBlock buf(BUF_SIZE);
00113 clock_t start = clock();
00114
00115 unsigned long i=0, blocks=1;
00116 double timeTaken;
00117 do
00118 {
00119 blocks *= 2;
00120 for (; i<blocks; i++)
00121 cipher.ProcessString(buf, BUF_SIZE);
00122 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
00123 }
00124 while (timeTaken < 2.0/3*timeTotal);
00125
00126 OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
00127 }
00128
00129 void BenchMark(const char *name, HashTransformation &ht, double timeTotal)
00130 {
00131 const int BUF_SIZE=2048U;
00132 AlignedSecByteBlock buf(BUF_SIZE);
00133 LC_RNG rng((word32)time(NULL));
00134 rng.GenerateBlock(buf, BUF_SIZE);
00135 clock_t start = clock();
00136
00137 unsigned long i=0, blocks=1;
00138 double timeTaken;
00139 do
00140 {
00141 blocks *= 2;
00142 for (; i<blocks; i++)
00143 ht.Update(buf, BUF_SIZE);
00144 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
00145 }
00146 while (timeTaken < 2.0/3*timeTotal);
00147
00148 OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
00149 }
00150
00151 void BenchMark(const char *name, BufferedTransformation &bt, double timeTotal)
00152 {
00153 const int BUF_SIZE=2048U;
00154 AlignedSecByteBlock buf(BUF_SIZE);
00155 LC_RNG rng((word32)time(NULL));
00156 rng.GenerateBlock(buf, BUF_SIZE);
00157 clock_t start = clock();
00158
00159 unsigned long i=0, blocks=1;
00160 double timeTaken;
00161 do
00162 {
00163 blocks *= 2;
00164 for (; i<blocks; i++)
00165 bt.Put(buf, BUF_SIZE);
00166 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
00167 }
00168 while (timeTaken < 2.0/3*timeTotal);
00169
00170 OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
00171 }
00172
00173 void BenchMarkKeying(SimpleKeyingInterface &c, size_t keyLength, const NameValuePairs ¶ms)
00174 {
00175 unsigned long iterations = 0;
00176 clock_t start = clock();
00177 double timeTaken;
00178 do
00179 {
00180 for (unsigned int i=0; i<1024; i++)
00181 c.SetKey(key, keyLength, params);
00182 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
00183 iterations += 1024;
00184 }
00185 while (timeTaken < g_allocatedTime);
00186
00187 OutputResultKeying(iterations, timeTaken);
00188 }
00189
00190
00191 template <class T>
00192 void BenchMarkKeyed(const char *name, double timeTotal, const NameValuePairs ¶ms = g_nullNameValuePairs, T *x=NULL)
00193 {
00194 T c;
00195 c.SetKey(key, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
00196 BenchMark(name, c, timeTotal);
00197 BenchMarkKeying(c, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
00198 }
00199
00200
00201 template <class T>
00202 void BenchMarkKeyedVariable(const char *name, double timeTotal, unsigned int keyLength, const NameValuePairs ¶ms = g_nullNameValuePairs, T *x=NULL)
00203 {
00204 T c;
00205 c.SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
00206 BenchMark(name, c, timeTotal);
00207 BenchMarkKeying(c, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
00208 }
00209
00210
00211 template <class T>
00212 void BenchMarkKeyless(const char *name, double timeTotal, T *x=NULL)
00213 {
00214 T c;
00215 BenchMark(name, c, timeTotal);
00216 }
00217
00218
00219 template <class T>
00220 void BenchMarkByName(const char *factoryName, size_t keyLength = 0, const char *displayName=NULL, const NameValuePairs ¶ms = g_nullNameValuePairs, T *x=NULL)
00221 {
00222 std::string name = factoryName;
00223 if (displayName)
00224 name = displayName;
00225 else if (keyLength)
00226 name += " (" + IntToString(keyLength * 8) + "-bit key)";
00227
00228 std::auto_ptr<T> obj(ObjectFactoryRegistry<T>::Registry().CreateObject(factoryName));
00229 if (!keyLength)
00230 keyLength = obj->DefaultKeyLength();
00231 obj->SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
00232 BenchMark(name.c_str(), *obj, g_allocatedTime);
00233 BenchMarkKeying(*obj, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
00234 }
00235
00236 template <class T>
00237 void BenchMarkByNameKeyLess(const char *factoryName, const char *displayName=NULL, const NameValuePairs ¶ms = g_nullNameValuePairs, T *x=NULL)
00238 {
00239 std::string name = factoryName;
00240 if (displayName)
00241 name = displayName;
00242
00243 std::auto_ptr<T> obj(ObjectFactoryRegistry<T>::Registry().CreateObject(factoryName));
00244 BenchMark(name.c_str(), *obj, g_allocatedTime);
00245 }
00246
00247 void BenchmarkAll(double t, double hertz)
00248 {
00249 #if 1
00250 logtotal = 0;
00251 logcount = 0;
00252 g_allocatedTime = t;
00253 g_hertz = hertz;
00254
00255 const char *cpb, *cpk;
00256 if (g_hertz)
00257 {
00258 cpb = "<TH>Cycles Per Byte";
00259 cpk = "<TH>Cycles to<br>Setup Key and IV";
00260 cout << "CPU frequency of the test platform is " << g_hertz << " Hz.\n";
00261 }
00262 else
00263 {
00264 cpb = cpk = "";
00265 cout << "CPU frequency of the test platform was not provided.\n";
00266 }
00267
00268 cout << "<TABLE border=1><COLGROUP><COL align=left><COL align=right><COL align=right><COL align=right><COL align=right>" << endl;
00269 cout << "<THEAD><TR><TH>Algorithm<TH>MiB/Second" << cpb << "<TH>Microseconds to<br>Setup Key and IV" << cpk << endl;
00270
00271 cout << "\n<TBODY style=\"background: white\">";
00272 BenchMarkByName<MessageAuthenticationCode>("VMAC(AES)-64");
00273 BenchMarkByName<MessageAuthenticationCode>("VMAC(AES)-128");
00274 BenchMarkByName<MessageAuthenticationCode>("HMAC(SHA-1)");
00275 BenchMarkByName<MessageAuthenticationCode>("Two-Track-MAC");
00276 BenchMarkKeyed<CBC_MAC<AES> >("CBC-MAC/AES", t);
00277 BenchMarkKeyed<DMAC<AES> >("DMAC/AES", t);
00278
00279 cout << "\n<TBODY style=\"background: yellow\">";
00280 BenchMarkKeyless<CRC32>("CRC-32", t);
00281 BenchMarkKeyless<Adler32>("Adler-32", t);
00282 BenchMarkByNameKeyLess<HashTransformation>("MD5");
00283 BenchMarkByNameKeyLess<HashTransformation>("SHA-1");
00284 BenchMarkByNameKeyLess<HashTransformation>("SHA-256");
00285 #ifdef WORD64_AVAILABLE
00286 BenchMarkByNameKeyLess<HashTransformation>("SHA-512");
00287 BenchMarkByNameKeyLess<HashTransformation>("Tiger");
00288 BenchMarkByNameKeyLess<HashTransformation>("Whirlpool");
00289 #endif
00290 BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-160");
00291 BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-320");
00292 BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-128");
00293 BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-256");
00294
00295 cout << "\n<TBODY style=\"background: white\">";
00296 BenchMarkByName<SymmetricCipher>("Panama-LE");
00297 BenchMarkByName<SymmetricCipher>("Panama-BE");
00298 BenchMarkByName<SymmetricCipher>("Salsa20");
00299 BenchMarkByName<SymmetricCipher>("Salsa20", 0, "Salsa20/12", MakeParameters(Name::Rounds(), 12));
00300 BenchMarkByName<SymmetricCipher>("Salsa20", 0, "Salsa20/8", MakeParameters(Name::Rounds(), 8));
00301 BenchMarkByName<SymmetricCipher>("Sosemanuk");
00302 BenchMarkByName<SymmetricCipher>("MARC4");
00303 BenchMarkKeyed<SEAL<BigEndian>::Encryption>("SEAL-3.0-BE", t);
00304 BenchMarkKeyed<SEAL<LittleEndian>::Encryption>("SEAL-3.0-LE", t);
00305 BenchMarkKeyed<WAKE_OFB<BigEndian>::Encryption>("WAKE-OFB-BE", t);
00306 BenchMarkKeyed<WAKE_OFB<LittleEndian>::Encryption>("WAKE-OFB-LE", t);
00307
00308 cout << "\n<TBODY style=\"background: yellow\">";
00309 BenchMarkByName<SymmetricCipher>("AES/ECB", 16);
00310 BenchMarkByName<SymmetricCipher>("AES/ECB", 24);
00311 BenchMarkByName<SymmetricCipher>("AES/ECB", 32);
00312 BenchMarkByName<SymmetricCipher>("AES/CTR", 16);
00313 BenchMarkByName<SymmetricCipher>("AES/OFB", 16);
00314 BenchMarkByName<SymmetricCipher>("AES/CFB", 16);
00315 BenchMarkByName<SymmetricCipher>("AES/CBC", 16);
00316 BenchMarkByName<SymmetricCipher>("Camellia/ECB", 16);
00317 BenchMarkByName<SymmetricCipher>("Camellia/ECB", 32);
00318 BenchMarkKeyed<Twofish::Encryption>("Twofish", t);
00319 BenchMarkKeyed<Serpent::Encryption>("Serpent", t);
00320 BenchMarkKeyed<CAST256::Encryption>("CAST-256", t);
00321 BenchMarkKeyed<RC6::Encryption>("RC6", t);
00322 BenchMarkKeyed<MARS::Encryption>("MARS", t);
00323 BenchMarkByName<SymmetricCipher>("SHACAL-2/ECB", 16);
00324 BenchMarkByName<SymmetricCipher>("SHACAL-2/ECB", 64);
00325 BenchMarkKeyed<DES::Encryption>("DES", t);
00326 BenchMarkKeyed<DES_XEX3::Encryption>("DES-XEX3", t);
00327 BenchMarkKeyed<DES_EDE3::Encryption>("DES-EDE3", t);
00328 BenchMarkKeyed<IDEA::Encryption>("IDEA", t);
00329 BenchMarkKeyed<RC5::Encryption>("RC5 (r=16)", t);
00330 BenchMarkKeyed<Blowfish::Encryption>("Blowfish", t);
00331 BenchMarkByName<SymmetricCipher>("TEA/ECB");
00332 BenchMarkByName<SymmetricCipher>("XTEA/ECB");
00333 BenchMarkKeyed<CAST128::Encryption>("CAST-128", t);
00334 BenchMarkKeyed<SKIPJACK::Encryption>("SKIPJACK", t);
00335 cout << "</TABLE>" << endl;
00336
00337 BenchmarkAll2(t, hertz);
00338
00339 cout << "Throughput Geometric Average: " << setiosflags(ios::fixed) << exp(logtotal/logcount) << endl;
00340
00341 time_t endTime = time(NULL);
00342 cout << "\nTest ended at " << asctime(localtime(&endTime));
00343 #endif
00344 }