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.
 
 
 
 
 

203 lines
6.4 KiB

  1. /**
  2. * @file test_decaf.cxx
  3. * @author Mike Hamburg
  4. *
  5. * @copyright
  6. * Copyright (c) 2015 Cryptography Research, Inc. \n
  7. * Released under the MIT License. See LICENSE.txt for license information.
  8. *
  9. * @brief C++ benchmarks, because that's easier.
  10. */
  11. #include "decaf.hxx"
  12. #include "shake.hxx"
  13. #include "shake.h"
  14. #include "decaf_crypto.h"
  15. #include <stdio.h>
  16. #include <sys/time.h>
  17. #include <assert.h>
  18. #include <stdint.h>
  19. typedef decaf::decaf<448>::Scalar Scalar;
  20. typedef decaf::decaf<448>::Point Point;
  21. typedef decaf::decaf<448>::Precomputed Precomputed;
  22. static __inline__ void __attribute__((unused)) ignore_result ( int result ) { (void)result; }
  23. static double now(void) {
  24. struct timeval tv;
  25. gettimeofday(&tv, NULL);
  26. return tv.tv_sec + tv.tv_usec/1000000.0;
  27. }
  28. // RDTSC from the chacha code
  29. #ifndef __has_builtin
  30. #define __has_builtin(X) 0
  31. #endif
  32. #if defined(__clang__) && __has_builtin(__builtin_readcyclecounter)
  33. #define rdtsc __builtin_readcyclecounter
  34. #else
  35. static inline uint64_t rdtsc(void) {
  36. u_int64_t out = 0;
  37. # if (defined(__i386__) || defined(__x86_64__))
  38. __asm__ __volatile__ ("rdtsc" : "=A"(out));
  39. # endif
  40. return out;
  41. }
  42. #endif
  43. static void printSI(double x, const char *unit, const char *spacer = " ") {
  44. const char *small[] = {" ","m","ยต","n","p"};
  45. const char *big[] = {" ","k","M","G","T"};
  46. if (x < 1) {
  47. unsigned di=0;
  48. for (di=0; di<sizeof(small)/sizeof(*small)-1 && x && x < 1; di++) {
  49. x *= 1000.0;
  50. }
  51. printf("%6.2f%s%s%s", x, spacer, small[di], unit);
  52. } else {
  53. unsigned di=0;
  54. for (di=0; di<sizeof(big)/sizeof(*big)-1 && x && x >= 1000; di++) {
  55. x /= 1000.0;
  56. }
  57. printf("%6.2f%s%s%s", x, spacer, big[di], unit);
  58. }
  59. }
  60. class Benchmark {
  61. static const int NTESTS = 1000;
  62. static double totalCy, totalS;
  63. /* FIXME Tcy if get descheduled */
  64. public:
  65. int i, ntests;
  66. double begin;
  67. uint64_t tsc_begin;
  68. Benchmark(const char *s, double factor = 1) {
  69. printf("%s:", s);
  70. if (strlen(s) < 25) printf("%*s",int(25-strlen(s)),"");
  71. fflush(stdout);
  72. i = 0;
  73. ntests = NTESTS * factor;
  74. begin = now();
  75. tsc_begin = rdtsc();
  76. }
  77. ~Benchmark() {
  78. double tsc = (rdtsc() - tsc_begin) * 1.0;
  79. double t = (now() - begin);
  80. totalCy += tsc;
  81. totalS += t;
  82. t /= ntests;
  83. tsc /= ntests;
  84. printSI(t,"s");
  85. printf(" ");
  86. printSI(1/t,"/s");
  87. if (tsc) { printf(" "); printSI(tsc, "cy"); }
  88. printf("\n");
  89. }
  90. inline bool iter() { return i++ < ntests; }
  91. static void calib() {
  92. if (totalS && totalCy) {
  93. const char *s = "Cycle calibration";
  94. printf("%s:", s);
  95. if (strlen(s) < 25) printf("%*s",int(25-strlen(s)),"");
  96. printSI(totalCy / totalS, "Hz");
  97. printf("\n");
  98. }
  99. }
  100. };
  101. double Benchmark::totalCy = 0, Benchmark::totalS = 0;
  102. int main(int argc, char **argv) {
  103. bool micro = false;
  104. if (argc >= 2 && !strcmp(argv[1], "--micro"))
  105. micro = true;
  106. decaf_448_public_key_t p1,p2;
  107. decaf_448_private_key_t s1,s2;
  108. decaf_448_symmetric_key_t r1,r2;
  109. decaf_448_signature_t sig1;
  110. unsigned char ss[32];
  111. memset(r1,1,sizeof(r1));
  112. memset(r2,2,sizeof(r2));
  113. unsigned char umessage[] = {1,2,3,4,5};
  114. size_t lmessage = sizeof(umessage);
  115. printf("\n");
  116. if (micro) {
  117. Precomputed pBase;
  118. Point p,q;
  119. Scalar s,t;
  120. decaf::SecureBuffer ep, ep2(Point::SER_BYTES*2);
  121. printf("Micro-benchmarks:\n");
  122. decaf::SHAKE<128> shake1;
  123. decaf::SHAKE<256> shake2;
  124. decaf::SHA3<512> sha5;
  125. decaf::Strobe strobe(decaf::Strobe::CLIENT);
  126. unsigned char b1024[1024] = {1};
  127. for (Benchmark b("SHAKE128 1kiB", 30); b.iter(); ) { shake1 += decaf::TmpBuffer(b1024,1024); }
  128. for (Benchmark b("SHAKE256 1kiB", 30); b.iter(); ) { shake2 += decaf::TmpBuffer(b1024,1024); }
  129. for (Benchmark b("SHA3-512 1kiB", 30); b.iter(); ) { sha5 += decaf::TmpBuffer(b1024,1024); }
  130. strobe.key(decaf::TmpBuffer(b1024,1024));
  131. for (Benchmark b("STROBE256 1kiB", 30); b.iter(); ) {
  132. strobe.encrypt_no_auth(decaf::TmpBuffer(b1024,1024),decaf::TmpBuffer(b1024,1024),b.i>1);
  133. }
  134. strobe.respec(STROBE_KEYED_128);
  135. for (Benchmark b("STROBEk128 1kiB", 30); b.iter(); ) {
  136. strobe.encrypt_no_auth(decaf::TmpBuffer(b1024,1024),decaf::TmpBuffer(b1024,1024),b.i>1);
  137. }
  138. for (Benchmark b("Scalar add", 1000); b.iter(); ) { s+=t; }
  139. for (Benchmark b("Scalar times", 100); b.iter(); ) { s*=t; }
  140. for (Benchmark b("Scalar inv", 1); b.iter(); ) { s.inverse(); }
  141. for (Benchmark b("Point add", 100); b.iter(); ) { p += q; }
  142. for (Benchmark b("Point double", 100); b.iter(); ) { p.double_in_place(); }
  143. for (Benchmark b("Point scalarmul"); b.iter(); ) { p * s; }
  144. for (Benchmark b("Point encode"); b.iter(); ) { ep = decaf::SecureBuffer(p); }
  145. for (Benchmark b("Point decode"); b.iter(); ) { p = Point(ep); }
  146. for (Benchmark b("Point create/destroy"); b.iter(); ) { Point r; }
  147. for (Benchmark b("Point hash nonuniform"); b.iter(); ) { Point::from_hash(ep); }
  148. for (Benchmark b("Point hash uniform"); b.iter(); ) { Point::from_hash(ep2); }
  149. for (Benchmark b("Point double scalarmul"); b.iter(); ) { Point::double_scalarmul(p,s,q,t); }
  150. for (Benchmark b("Point precmp scalarmul"); b.iter(); ) { pBase * s; }
  151. /* TODO: scalarmul for verif, etc */
  152. printf("\nMacro-benchmarks:\n");
  153. }
  154. for (Benchmark b("Keygen"); b.iter(); ) {
  155. decaf_448_derive_private_key(s1,r1);
  156. }
  157. decaf_448_private_to_public(p1,s1);
  158. decaf_448_derive_private_key(s2,r2);
  159. decaf_448_private_to_public(p2,s2);
  160. for (Benchmark b("Shared secret"); b.iter(); ) {
  161. decaf_bool_t ret = decaf_448_shared_secret(ss,sizeof(ss),s1,p2);
  162. ignore_result(ret);
  163. assert(ret);
  164. }
  165. for (Benchmark b("Sign"); b.iter(); ) {
  166. decaf_448_sign(sig1,s1,umessage,lmessage);
  167. }
  168. for (Benchmark b("Verify"); b.iter(); ) {
  169. decaf_bool_t ret = decaf_448_verify(sig1,p1,umessage,lmessage);
  170. umessage[0]++;
  171. umessage[1]^=umessage[0];
  172. ignore_result(ret);
  173. }
  174. printf("\n");
  175. Benchmark::calib();
  176. printf("\n");
  177. return 0;
  178. }