]> jfr.im git - irc/atheme/atheme.git/commitdiff
src/crypto-benchmark/: consolidate code & fixups
authorAaron Jones <redacted>
Wed, 15 Jan 2020 06:54:10 +0000 (06:54 +0000)
committerAaron Jones <redacted>
Wed, 15 Jan 2020 06:54:30 +0000 (06:54 +0000)
- Combine two related small source files into one

- Add missing header inclusion

  It didn't prevent compilation, but it should be included

- Don't print benchmark information twice when not running in
  optimal mode

- Make operation modes exclusionary

- Rename variables in main.c for clearer identification of
  their purpose

- Calculate bench_short_opts[] dynamically from the contents of
  the bench_long_opts[] array

  This will aid future refactoring or feature additions without
  introducing option parsing regressions

- Always print version and library information at start-up

- Rename some command-line options for clearer identification

- Print valid types & digests for Argon2 & PBKDF2 in --help

- Cap the wall-clock time limits (minimum and maximum) for -g

- Remind user they should give -l if giving -o

  But don't print anything if they gave -l but kept it at the
  default value

- Use `unsigned long long' where appropriate to prevent unsigned
  integer truncation or nonsense bit-shifts

- Don't run unnecessary further iteration in optimal bench-
  marking mode if we just so happen to land exactly at the wall-
  clock time limit first

- Clarify note with regards to SASL SCRAM in optimal PBKDF2
  benchmark output

- Document simpler determination methodology in optimal PBKDF2
  benchmarking

src/crypto-benchmark/Makefile
src/crypto-benchmark/benchmark.c
src/crypto-benchmark/benchmark.h
src/crypto-benchmark/main.c
src/crypto-benchmark/optimal.c
src/crypto-benchmark/optimal.h
src/crypto-benchmark/utils.c [deleted file]
src/crypto-benchmark/utils.h [deleted file]

index 138b161b65f7b9958802ec8d43979711f45bdc72..2625293da5518a53c8ece2700bf3f049e0e370ad 100644 (file)
@@ -1,5 +1,5 @@
 PROG           = $(PACKAGE)-crypto-benchmark${PROG_SUFFIX}
-SRCS           = benchmark.c main.c optimal.c utils.c
+SRCS           = benchmark.c main.c optimal.c
 
 include ../../extra.mk
 include ../../buildsys.mk
index 426c71b3b13b3972b13f757b8a235522dd3278a5..810d838bc31f5ac98e44a3af4ab76d6d50ca2bd6 100644 (file)
 #include <atheme/stdheaders.h>      // (everything else)
 #include <atheme/sysconf.h>         // HAVE_LIBARGON2
 
-#include "benchmark.h"              // self-declarations
-#include "utils.h"                  // (everything else)
+#include "benchmark.h"              // (everything else)
+
+#ifdef HAVE_LIBARGON2
+#  include <argon2.h>               // argon2_context, argon2_type, argon2_*(), ARGON2_VERSION_NUMBER
+#endif
 
 static const long double nsec_per_sec = 1000000000.0L;
 
-static unsigned char hashbuf[BUFSIZE];
 static unsigned char saltbuf[BUFSIZE];
-static char passbuf[PASSLEN + 1];
+static char hashbuf[BUFSIZE];
+static char passbuf[BUFSIZE];
 
 bool ATHEME_FATTR_WUR
 benchmark_init(void)
@@ -41,12 +44,44 @@ benchmark_init(void)
 
 #ifdef HAVE_LIBARGON2
 
+argon2_type
+argon2_name_to_type(const char *const restrict b_name)
+{
+       if (strcasecmp(b_name, "Argon2d") == 0)
+               return Argon2_d;
+       else if (strcasecmp(b_name, "Argon2i") == 0)
+               return Argon2_i;
+       else if (strcasecmp(b_name, "Argon2id") == 0)
+               return Argon2_id;
+
+       (void) fprintf(stderr, "%s: '%s' is not a valid type name\n", MOWGLI_FUNC_NAME, b_name);
+       (void) fprintf(stderr, "%s: valid names are: Argon2d, Argon2i, Argon2id\n", MOWGLI_FUNC_NAME);
+
+       exit(EXIT_FAILURE);
+}
+
+void
+argon2_print_colheaders(void)
+{
+       (void) fprintf(stderr, "%-10s %-14s %-10s %-10s %-14s\n",
+                              "Type", "MemCost", "TimeCost", "Threads", "Elapsed");
+       (void) fprintf(stderr, "---------- -------------- ---------- ---------- --------------\n");
+}
+
+void
+argon2_print_rowstats(const argon2_type type, const size_t memcost, const size_t timecost, const size_t threads,
+                      const long double elapsed)
+{
+       (void) fprintf(stderr, "%10s %13uK %10zu %10zu %13LFs\n", argon2_type2string(type, 1),
+                              (1U << memcost), timecost, threads, elapsed);
+}
+
 bool ATHEME_FATTR_WUR
 benchmark_argon2(const argon2_type type, const size_t memcost, const size_t timecost, const size_t threadcount,
                  long double *const restrict elapsed)
 {
        argon2_context ctx = {
-               .out            = hashbuf,
+               .out            = (void *) hashbuf,
                .outlen         = ARGON2_HASHLEN_DEF,
                .pwd            = (void *) passbuf,
                .pwdlen         = PASSLEN,
@@ -84,15 +119,66 @@ benchmark_argon2(const argon2_type type, const size_t memcost, const size_t time
 
        const long double begin_ld = ((long double) begin.tv_sec) + (((long double) begin.tv_nsec) / nsec_per_sec);
        const long double end_ld = ((long double) end.tv_sec) + (((long double) end.tv_nsec) / nsec_per_sec);
+       const long double duration = (end_ld - begin_ld);
 
-       *elapsed = (end_ld - begin_ld);
+       if (elapsed)
+               *elapsed = duration;
 
-       (void) argon2_print_rowstats(type, memcost, timecost, threadcount, *elapsed);
+       (void) argon2_print_rowstats(type, memcost, timecost, threadcount, duration);
        return true;
 }
 
 #endif /* HAVE_LIBARGON2 */
 
+const char *
+md_digest_to_name(const enum digest_algorithm b_digest)
+{
+       switch (b_digest)
+       {
+               case DIGALG_MD5:
+                       return "MD5";
+               case DIGALG_SHA1:
+                       return "SHA1";
+               case DIGALG_SHA2_256:
+                       return "SHA256";
+               case DIGALG_SHA2_512:
+                       return "SHA512";
+       }
+
+       return NULL;
+}
+
+enum digest_algorithm
+md_name_to_digest(const char *const restrict b_name)
+{
+       if (strcasecmp(b_name, "MD5") == 0)
+               return DIGALG_MD5;
+       else if (strcasecmp(b_name, "SHA1") == 0)
+               return DIGALG_SHA1;
+       else if (strcasecmp(b_name, "SHA2-256") == 0)
+               return DIGALG_SHA2_256;
+       else if (strcasecmp(b_name, "SHA2-512") == 0)
+               return DIGALG_SHA2_512;
+
+       (void) fprintf(stderr, "%s: '%s' is not a valid algorithm name\n", MOWGLI_FUNC_NAME, b_name);
+       (void) fprintf(stderr, "%s: valid names are: MD5, SHA1, SHA2-256, SHA2-512\n", MOWGLI_FUNC_NAME);
+
+       exit(EXIT_FAILURE);
+}
+
+void
+pbkdf2_print_colheaders(void)
+{
+       (void) fprintf(stderr, "%-10s %-10s %-14s\n", "Digest", "Iterations", "Elapsed");
+       (void) fprintf(stderr, "---------- ---------- --------------\n");
+}
+
+void
+pbkdf2_print_rowstats(const enum digest_algorithm digest, const size_t iterations, const long double elapsed)
+{
+       (void) fprintf(stderr, "%10s %10zu %13LFs\n", md_digest_to_name(digest), iterations, elapsed);
+}
+
 bool ATHEME_FATTR_WUR
 benchmark_pbkdf2(const enum digest_algorithm digest, const size_t itercount, long double *const restrict elapsed)
 {
@@ -121,9 +207,11 @@ benchmark_pbkdf2(const enum digest_algorithm digest, const size_t itercount, lon
 
        const long double begin_ld = ((long double) begin.tv_sec) + (((long double) begin.tv_nsec) / nsec_per_sec);
        const long double end_ld = ((long double) end.tv_sec) + (((long double) end.tv_nsec) / nsec_per_sec);
+       const long double duration = (end_ld - begin_ld);
 
-       *elapsed = (end_ld - begin_ld);
+       if (elapsed)
+               *elapsed = duration;
 
-       (void) pbkdf2_print_rowstats(digest, itercount, *elapsed);
+       (void) pbkdf2_print_rowstats(digest, itercount, duration);
        return true;
 }
index fee539b6471cd7a1b27c1c0ca1f3cfa32608323f..897c934957cd580519878bb8f0c9612118494a21 100644 (file)
 #ifndef ATHEME_SRC_CRYPTO_BENCHMARK_BENCHMARK_H
 #define ATHEME_SRC_CRYPTO_BENCHMARK_BENCHMARK_H 1
 
-#include <atheme/attributes.h>  // ATHEME_FATTR_WUR
-#include <atheme/digest.h>      // enum digest_algorithm
-#include <atheme/stdheaders.h>  // bool
-#include <atheme/sysconf.h>     // HAVE_LIBARGON2
+#include <atheme/attributes.h>      // ATHEME_FATTR_WUR
+#include <atheme/digest.h>          // enum digest_algorithm
+#include <atheme/stdheaders.h>      // bool
+#include <atheme/sysconf.h>         // HAVE_*
 
 #ifdef HAVE_LIBARGON2
-#  include <argon2.h>           // argon2_type
+#  include <argon2.h>               // argon2_type
 #endif
 
+#define BENCH_MAX(a, b)             (((a) <= (b)) ? (b) : (a))
+#define BENCH_MIN(a, b)             (((a) <= (b)) ? (a) : (b))
+
+#define BENCH_RUN_OPTIONS_NONE      0x0000U
+#define BENCH_RUN_OPTIONS_OPTIMAL   0x0001U
+#define BENCH_RUN_OPTIONS_ARGON2    0x0002U
+#define BENCH_RUN_OPTIONS_PBKDF2    0x0004U
+
 bool benchmark_init(void) ATHEME_FATTR_WUR;
 
 #ifdef HAVE_LIBARGON2
-bool benchmark_argon2(const argon2_type, size_t, size_t, size_t, long double *) ATHEME_FATTR_WUR;
+argon2_type argon2_name_to_type(const char *);
+void argon2_print_colheaders(void);
+void argon2_print_rowstats(argon2_type, size_t, size_t, size_t, long double);
+bool benchmark_argon2(argon2_type, size_t, size_t, size_t, long double *) ATHEME_FATTR_WUR;
 #endif
 
+enum digest_algorithm md_name_to_digest(const char *);
+const char *md_digest_to_name(enum digest_algorithm);
+void pbkdf2_print_colheaders(void);
+void pbkdf2_print_rowstats(enum digest_algorithm, size_t, long double);
 bool benchmark_pbkdf2(enum digest_algorithm, size_t, long double *) ATHEME_FATTR_WUR;
 
 #endif /* !ATHEME_SRC_CRYPTO_BENCHMARK_BENCHMARK_H */
index b38181d6de0829f937483be8eae379c6e8284679..b1b59712ce5806c9876dbd342c071375a402e5db 100644 (file)
  * copyright notice and this permission notice appear in all copies.
  */
 
-#include <atheme/argon2.h>      // ARGON2_*
-#include <atheme/digest.h>      // DIGALG_*
-#include <atheme/memory.h>      // sreallocarray()
-#include <atheme/pbkdf2.h>      // PBKDF2_*
-#include <atheme/stdheaders.h>  // (everything else)
-#include <atheme/tools.h>       // string_to_uint()
+#include <atheme/argon2.h>          // ARGON2_*
+#include <atheme/digest.h>          // DIGALG_*
+#include <atheme/memory.h>          // sreallocarray()
+#include <atheme/pbkdf2.h>          // PBKDF2_*
+#include <atheme/stdheaders.h>      // (everything else)
+#include <atheme/sysconf.h>         // HAVE_LIBARGON2
+#include <atheme/tools.h>           // string_to_uint()
 
-#include <ext/getopt_long.h>    // mowgli_getopt_option_t, mowgli_getopt_long()
+#include <ext/getopt_long.h>        // mowgli_getopt_option_t, mowgli_getopt_long()
 
-#include "benchmark.h"          // benchmark_*()
-#include "optimal.h"            // do_optimal_benchmarks()
-#include "utils.h"              // (everything else)
+#include "benchmark.h"              // (everything else)
+#include "optimal.h"                // do_optimal_benchmarks()
 
-#define BENCH_ARRAY_SIZE(x)     ((sizeof((x))) / (sizeof((x)[0])))
-#define BENCH_CLOCKTIME_DEFAULT 0.25L
-#define BENCH_MEMLIMIT_DEFAULT  ARGON2_MEMCOST_DEF;
+#define BENCH_ARRAY_SIZE(x)         ((sizeof((x))) / (sizeof((x)[0])))
 
-static size_t b_itercounts_default[] = { PBKDF2_ITERCNT_MIN, PBKDF2_ITERCNT_DEF, PBKDF2_ITERCNT_MAX };
-static size_t *b_itercounts = NULL;
-static size_t b_itercounts_count = 0;
+#define BENCH_CLOCKTIME_MIN         0.10L
+#define BENCH_CLOCKTIME_DEF         0.25L
+#define BENCH_CLOCKTIME_MAX         1.00L
 
-static enum digest_algorithm b_digests_default[] = { DIGALG_SHA1, DIGALG_SHA2_256, DIGALG_SHA2_512 };
-static enum digest_algorithm *b_digests = NULL;
-static size_t b_digests_count = 0;
+#define BENCH_MEMLIMIT_MIN          ARGON2_MEMCOST_MIN
+#define BENCH_MEMLIMIT_DEF          ARGON2_MEMCOST_DEF
+#define BENCH_MEMLIMIT_MAX          ARGON2_MEMCOST_MAX
 
 #ifdef HAVE_LIBARGON2
 
-static argon2_type b_types_default[] = { Argon2_id };
-static argon2_type *b_types = NULL;
-static size_t b_types_count = 0;
+static argon2_type b_argon2_types_default[] = { Argon2_id };
+static argon2_type *b_argon2_types = NULL;
+static size_t b_argon2_types_count = 0;
 
-static size_t b_memcosts_default[] = { ARGON2_MEMCOST_MIN, ARGON2_MEMCOST_DEF };
-static size_t *b_memcosts = NULL;
-static size_t b_memcosts_count = 0;
+static size_t b_argon2_memcosts_default[] = { ARGON2_MEMCOST_MIN, ARGON2_MEMCOST_DEF };
+static size_t *b_argon2_memcosts = NULL;
+static size_t b_argon2_memcosts_count = 0;
 
-static size_t b_timecosts_default[] = { ARGON2_TIMECOST_MIN, ARGON2_TIMECOST_DEF };
-static size_t *b_timecosts = NULL;
-static size_t b_timecosts_count = 0;
+static size_t b_argon2_timecosts_default[] = { ARGON2_TIMECOST_MIN, ARGON2_TIMECOST_DEF };
+static size_t *b_argon2_timecosts = NULL;
+static size_t b_argon2_timecosts_count = 0;
 
-static size_t b_threads_default[] = { ARGON2_THREADS_DEF };
-static size_t *b_threads = NULL;
-static size_t b_threads_count = 0;
+static size_t b_argon2_threads_default[] = { ARGON2_THREADS_DEF };
+static size_t *b_argon2_threads = NULL;
+static size_t b_argon2_threads_count = 0;
 
 #endif /* HAVE_LIBARGON2 */
 
-static long double optimal_clocklimit = BENCH_CLOCKTIME_DEFAULT;
-static unsigned int optimal_memlimit = BENCH_MEMLIMIT_DEFAULT;
+static size_t b_pbkdf2_itercounts_default[] = { PBKDF2_ITERCNT_MIN, PBKDF2_ITERCNT_DEF, PBKDF2_ITERCNT_MAX };
+static size_t *b_pbkdf2_itercounts = NULL;
+static size_t b_pbkdf2_itercounts_count = 0;
 
-static bool run_optimal_benchmarks = false;
-static bool run_argon2_benchmarks = false;
-static bool run_pbkdf2_benchmarks = false;
+static enum digest_algorithm b_pbkdf2_digests_default[] = { DIGALG_SHA1, DIGALG_SHA2_256, DIGALG_SHA2_512 };
+static enum digest_algorithm *b_pbkdf2_digests = NULL;
+static size_t b_pbkdf2_digests_count = 0;
 
-#ifdef HAVE_LIBARGON2
-static const char bench_short_opts[] = "hvog:l:an:m:t:p:kc:d:";
-#else
-static const char bench_short_opts[] = "hvog:kc:d:";
-#endif
+static long double optimal_clocklimit = BENCH_CLOCKTIME_DEF;
+static unsigned int optimal_memlimit = BENCH_MEMLIMIT_DEF;
+static bool optimal_memlimit_given = false;
+
+static unsigned int run_options = BENCH_RUN_OPTIONS_NONE;
 
 static const mowgli_getopt_option_t bench_long_opts[] = {
-       {       "help",       no_argument, NULL, 'h', 0 },
-       {    "version",       no_argument, NULL, 'v', 0 },
-       {    "optimal",       no_argument, NULL, 'o', 0 },
-       { "clocklimit", required_argument, NULL, 'g', 0 },
+
+       {                     "help",       no_argument, NULL, 'h', 0 },
+       {                  "version",       no_argument, NULL, 'v', 0 },
+
+       {   "run-optimal-benchmarks",       no_argument, NULL, 'o', 0 },
+       {      "optimal-clock-limit", required_argument, NULL, 'g', 0 },
 #ifdef HAVE_LIBARGON2
-       {   "memlimit", required_argument, NULL, 'l', 0 },
-       {     "argon2",       no_argument, NULL, 'a', 0 },
-       {       "type", required_argument, NULL, 'n', 0 },
-       {     "memory", required_argument, NULL, 'm', 0 },
-       {       "time", required_argument, NULL, 't', 0 },
-       {    "threads", required_argument, NULL, 'p', 0 },
+       {     "optimal-memory-limit", required_argument, NULL, 'l', 0 },
+       {    "run-argon2-benchmarks",       no_argument, NULL, 'a', 0 },
+       {             "argon2-types", required_argument, NULL, 'n', 0 },
+       {      "argon2-memory-costs", required_argument, NULL, 'm', 0 },
+       {        "argon2-time-costs", required_argument, NULL, 't', 0 },
+       {           "argon2-threads", required_argument, NULL, 'p', 0 },
 #endif
-       {     "pbkdf2",       no_argument, NULL, 'k', 0 },
-       { "iterations", required_argument, NULL, 'c', 0 },
-       {    "digests", required_argument, NULL, 'd', 0 },
-       {         NULL,                 0, NULL,  0 , 0 },
+       {    "run-pbkdf2-benchmarks",       no_argument, NULL, 'k', 0 },
+       {        "pbkdf2-iterations", required_argument, NULL, 'c', 0 },
+       { "pbkdf2-digest-algorithms", required_argument, NULL, 'd', 0 },
+
+       { NULL, 0, NULL, 0, 0 },
 };
 
+static inline void
+print_version(void)
+{
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "%s (Cryptographic Benchmarking Utility)\n", PACKAGE_STRING);
+       (void) fprintf(stderr, "Using digest frontend: %s\n", digest_get_frontend_info());
+}
+
 static inline void
 print_usage(void)
 {
        (void) fprintf(stderr, "\n"
-       "  Usage: " PACKAGE_TARNAME "-crypto-benchmark [-h | -v]\n"
-       "  Usage: " PACKAGE_TARNAME "-crypto-benchmark -o [-g <clocklimit>] [-l <memlimit>]\n"
+       "  Usage: " PACKAGE_TARNAME "-crypto-benchmark -h\n"
+       "         " PACKAGE_TARNAME "-crypto-benchmark -v\n"
+       "         " PACKAGE_TARNAME "-crypto-benchmark -o [-g ...] [-l ...]\n"
 #ifdef HAVE_LIBARGON2
-       "         " PACKAGE_TARNAME "-crypto-benchmark -a [-m ...] [-n ...] [-p ...] [-t ...]\n"
+       "         " PACKAGE_TARNAME "-crypto-benchmark -a [-n ...] [-m ...] [-t ...] [-p ...]\n"
 #endif
        "         " PACKAGE_TARNAME "-crypto-benchmark -k [-c ...] [-d ...]\n"
        "\n"
-       "  -h/--help        Display this help information and exit\n"
-       "  -v/--version     Display program version and exit\n"
+       "  -h/--help                    Display this help information and exit\n"
+       "  -v/--version                 Display program version and exit\n"
        "\n"
-       "  -o/--optimal     Perform an automatic optimal parameter benchmark\n"
-       "  -g/--clocklimit  Wall clock time limit for optimal benchmarking (seconds)\n"
+       "  -o/--run-optimal-benchmarks  Perform an automatic parameter tuning benchmark:\n"
+       "  -g/--optimal-clock-limit       Wall clock time limit for optimal benchmarks\n"
+       "                                   (in seconds, fractional values accepted)\n"
 #ifdef HAVE_LIBARGON2
-       "  -l/--memlimit    Memory limit for optimal benchmarking (power of 2, in KiB)\n"
-       "                     For example, '-l 16' means 2^16 KiB; 65536 KiB; 64 MiB\n"
+       "  -l/--optimal-memory-limit      Memory limit for optimal benchmarking\n"
+       "                                   (as a power of 2, in KiB)\n"
+       "                                   For example, '-l 16' means 2^16 KiB; 64 MiB\n"
 #else
-       "  -l/--memlimit    Unsupported\n"
+       "  -l/--optimal-memory-limit      Unsupported\n"
 #endif
        "\n"
        "    If one of the above limits are not given, defaults are used.\n"
 #ifdef HAVE_LIBARGON2
        "\n"
-       "  -a/--argon2      Benchmark the Argon2 code over a variety of configurations\n"
-       "  -m/--memory      Comma-separated Argon2 memory costs to benchmark\n"
-       "  -n/--type        Comma-separated Argon2 types to benchmark\n"
-       "  -p/--threads     Comma-separated Argon2 thread counts to benchmark\n"
-       "  -t/--time        Comma-separated Argon2 time costs to benchmark\n"
+       "  -a/--run-argon2-benchmarks   Benchmark the Argon2 code with configurations:\n"
+       "  -n/--argon2-types              Comma-separated types\n"
+       "  -m/--argon2-memory-costs       Comma-separated memory costs\n"
+       "  -t/--argon2-time-costs         Comma-separated time costs\n"
+       "  -p/--argon2-threads            Comma-separated thread counts\n"
+       "\n"
+       "    Valid types are: Argon2d, Argon2i, Argon2id (case-insensitive)\n"
 #endif
        "\n"
-       "  -k/--pbkdf2      Benchmark the PBKDF2 code over a variety of configurations\n"
-       "  -c/--iterations  Comma-separated PBKDF2 iteration counts to benchmark\n"
-       "  -d/--digests     Comma-separated PBKDF2 digest algorithms to benchmark\n"
+       "  -k/--run-pbkdf2-benchmarks   Benchmark the PBKDF2 code with configurations:\n"
+       "  -c/--pbkdf2-iterations         Comma-separated iteration counts\n"
+       "  -d/--pbkdf2-digests            Comma-separated digest algorithms\n"
+       "\n"
+       "    Valid digests are: MD5, SHA1, SHA2-256, SHA2-512 (case-insensitive)\n"
        "\n"
        "    If one of the comma-separated options are not given, defaults are used.\n"
        "\n");
@@ -165,10 +182,28 @@ process_uint_option(const int sw, const char *const restrict val, size_t **const
 static bool
 process_options(int argc, char *argv[])
 {
+       char bench_short_opts[BUFSIZE];
+
+       char *ptr = bench_short_opts;
        char *opt;
        char *tok;
        int c;
 
+       (void) memset(bench_short_opts, 0x00, sizeof bench_short_opts);
+
+       for (size_t x = 0; bench_long_opts[x].name != NULL; x++)
+       {
+               *ptr++ = bench_long_opts[x].val;
+
+               if (bench_long_opts[x].has_arg == no_argument)
+                       continue;
+
+               *ptr++ = ':';
+
+               if (bench_long_opts[x].has_arg == optional_argument)
+                       *ptr++ = ':';
+       }
+
        while ((c = mowgli_getopt_long(argc, argv, bench_short_opts, bench_long_opts, NULL)) != -1)
        {
                switch (c)
@@ -178,11 +213,11 @@ process_options(int argc, char *argv[])
                                exit(EXIT_SUCCESS);
 
                        case 'v':
-                               (void) fprintf(stderr, "%s\n", PACKAGE_STRING);
+                               // Version string was already printed at program startup
                                exit(EXIT_SUCCESS);
 
                        case 'o':
-                               run_optimal_benchmarks = true;
+                               run_options |= BENCH_RUN_OPTIONS_OPTIMAL;
                                break;
 
                        case 'g':
@@ -192,12 +227,20 @@ process_options(int argc, char *argv[])
                                char *end = NULL;
                                const long double ret = strtold(mowgli_optarg, &end);
 
-                               if (! ret || (end && *end))
+                               if (! ret || (end && *end) || errno != 0)
                                {
                                        (void) fprintf(stderr, "'%s' is not a valid value for decimal option '%c'\n",
                                                               mowgli_optarg, c);
                                        return false;
                                }
+                               if (ret < BENCH_CLOCKTIME_MIN || ret > BENCH_CLOCKTIME_MAX)
+                               {
+                                       (void) fprintf(stderr, "'%s' is not a valid value for decimal option '%c'\n",
+                                                              mowgli_optarg, c);
+                                       (void) fprintf(stderr, "range of valid values: %LF to %LF (inclusive)\n",
+                                                              BENCH_CLOCKTIME_MIN, BENCH_CLOCKTIME_MAX);
+                                       return false;
+                               }
 
                                optimal_clocklimit = ret;
                                break;
@@ -210,21 +253,22 @@ process_options(int argc, char *argv[])
                                        (void) fprintf(stderr, "'%s' is not a valid value for integer option '%c'\n",
                                                               mowgli_optarg, c);
                                        (void) fprintf(stderr, "range of valid values: %u to %u (inclusive)\n",
-                                                              ARGON2_MEMCOST_MIN, ARGON2_MEMCOST_MAX);
+                                                              BENCH_MEMLIMIT_MIN, BENCH_MEMLIMIT_MAX);
                                        return false;
                                }
-                               if (optimal_memlimit < ARGON2_MEMCOST_MIN || optimal_memlimit > ARGON2_MEMCOST_MAX)
+                               if (optimal_memlimit < BENCH_MEMLIMIT_MIN || optimal_memlimit > BENCH_MEMLIMIT_MAX)
                                {
                                        (void) fprintf(stderr, "'%u' is not a valid value for integer option '%c'\n",
                                                               optimal_memlimit, c);
                                        (void) fprintf(stderr, "range of valid values: %u to %u (inclusive)\n",
-                                                              ARGON2_MEMCOST_MIN, ARGON2_MEMCOST_MAX);
+                                                              BENCH_MEMLIMIT_MIN, BENCH_MEMLIMIT_MAX);
                                        return false;
                                }
+                               optimal_memlimit_given = true;
                                break;
 
                        case 'a':
-                               run_argon2_benchmarks = true;
+                               run_options |= BENCH_RUN_OPTIONS_ARGON2;
                                break;
 
                        case 'n':
@@ -236,15 +280,17 @@ process_options(int argc, char *argv[])
                                }
                                while ((tok = strsep(&opt, ",")) != NULL)
                                {
-                                       const argon2_type b_type = argon2_name_to_type(tok);
+                                       const argon2_type b_argon2_type = argon2_name_to_type(tok);
 
-                                       if (! (b_types = sreallocarray(b_types, b_types_count + 1, sizeof b_type)))
+                                       if (! (b_argon2_types = sreallocarray(b_argon2_types,
+                                                                             b_argon2_types_count + 1,
+                                                                             sizeof b_argon2_type)))
                                        {
                                                (void) perror("sreallocarray()");
                                                return false;
                                        }
 
-                                       b_types[b_types_count++] = b_type;
+                                       b_argon2_types[b_argon2_types_count++] = b_argon2_type;
                                }
 
                                (void) free(opt);
@@ -252,24 +298,27 @@ process_options(int argc, char *argv[])
                        }
 
                        case 'm':
-                               if (! process_uint_option(c, mowgli_optarg, &b_memcosts, &b_memcosts_count,
-                                                         ARGON2_MEMCOST_MIN, ARGON2_MEMCOST_MAX))
+                               if (! process_uint_option(c, mowgli_optarg, &b_argon2_memcosts,
+                                                         &b_argon2_memcosts_count, ARGON2_MEMCOST_MIN,
+                                                         ARGON2_MEMCOST_MAX))
                                        // This function logs error messages on failure
                                        return false;
 
                                break;
 
                        case 't':
-                               if (! process_uint_option(c, mowgli_optarg, &b_timecosts, &b_timecosts_count,
-                                                         ARGON2_TIMECOST_MIN, ARGON2_TIMECOST_MAX))
+                               if (! process_uint_option(c, mowgli_optarg, &b_argon2_timecosts,
+                                                         &b_argon2_timecosts_count, ARGON2_TIMECOST_MIN,
+                                                         ARGON2_TIMECOST_MAX))
                                        // This function logs error messages on failure
                                        return false;
 
                                break;
 
                        case 'p':
-                               if (! process_uint_option(c, mowgli_optarg, &b_threads, &b_threads_count,
-                                                         ARGON2_THREADS_MIN, ARGON2_THREADS_MAX))
+                               if (! process_uint_option(c, mowgli_optarg, &b_argon2_threads,
+                                                         &b_argon2_threads_count, ARGON2_THREADS_MIN,
+                                                         ARGON2_THREADS_MAX))
                                        // This function logs error messages on failure
                                        return false;
 
@@ -277,12 +326,13 @@ process_options(int argc, char *argv[])
 #endif /* HAVE_LIBARGON2 */
 
                        case 'k':
-                               run_pbkdf2_benchmarks = true;
+                               run_options |= BENCH_RUN_OPTIONS_PBKDF2;
                                break;
 
                        case 'c':
-                               if (! process_uint_option(c, mowgli_optarg, &b_itercounts, &b_itercounts_count,
-                                                         PBKDF2_ITERCNT_MIN, PBKDF2_ITERCNT_MAX))
+                               if (! process_uint_option(c, mowgli_optarg, &b_pbkdf2_itercounts,
+                                                         &b_pbkdf2_itercounts_count, PBKDF2_ITERCNT_MIN,
+                                                         PBKDF2_ITERCNT_MAX))
                                        // This function logs error messages on failure
                                        return false;
 
@@ -297,16 +347,17 @@ process_options(int argc, char *argv[])
                                }
                                while ((tok = strsep(&opt, ",")) != NULL)
                                {
-                                       const enum digest_algorithm b_digest = md_name_to_digest(tok);
+                                       const enum digest_algorithm b_pbkdf2_digest = md_name_to_digest(tok);
 
-                                       if (! (b_digests = sreallocarray(b_digests, b_digests_count + 1,
-                                                                        sizeof b_digest)))
+                                       if (! (b_pbkdf2_digests = sreallocarray(b_pbkdf2_digests,
+                                                                               b_pbkdf2_digests_count + 1,
+                                                                               sizeof b_pbkdf2_digest)))
                                        {
                                                (void) perror("sreallocarray()");
                                                return false;
                                        }
 
-                                       b_digests[b_digests_count++] = b_digest;
+                                       b_pbkdf2_digests[b_pbkdf2_digests_count++] = b_pbkdf2_digest;
                                }
 
                                (void) free(opt);
@@ -318,64 +369,53 @@ process_options(int argc, char *argv[])
                }
        }
 
-       if (! (run_optimal_benchmarks || run_argon2_benchmarks || run_pbkdf2_benchmarks))
+       if (! run_options || (run_options & (run_options - 1U)))
        {
                (void) print_usage();
+               (void) fprintf(stderr, "Error: Conflicting options (or no options) given.\n");
+               (void) fprintf(stderr, "\n");
                return false;
        }
 
-       if (! b_itercounts)
+#ifdef HAVE_LIBARGON2
+       if (! b_argon2_types)
        {
-               b_itercounts = b_itercounts_default;
-               b_itercounts_count = BENCH_ARRAY_SIZE(b_itercounts_default);
+               b_argon2_types = b_argon2_types_default;
+               b_argon2_types_count = BENCH_ARRAY_SIZE(b_argon2_types_default);
        }
-       if (! b_digests)
+       if (! b_argon2_memcosts)
        {
-               b_digests = b_digests_default;
-               b_digests_count = BENCH_ARRAY_SIZE(b_digests_default);
+               b_argon2_memcosts = b_argon2_memcosts_default;
+               b_argon2_memcosts_count = BENCH_ARRAY_SIZE(b_argon2_memcosts_default);
        }
-#ifdef HAVE_LIBARGON2
-       if (! b_types)
+       if (! b_argon2_timecosts)
        {
-               b_types = b_types_default;
-               b_types_count = BENCH_ARRAY_SIZE(b_types_default);
+               b_argon2_timecosts = b_argon2_timecosts_default;
+               b_argon2_timecosts_count = BENCH_ARRAY_SIZE(b_argon2_timecosts_default);
        }
-       if (! b_memcosts)
+       if (! b_argon2_threads)
        {
-               b_memcosts = b_memcosts_default;
-               b_memcosts_count = BENCH_ARRAY_SIZE(b_memcosts_default);
+               b_argon2_threads = b_argon2_threads_default;
+               b_argon2_threads_count = BENCH_ARRAY_SIZE(b_argon2_threads_default);
        }
-       if (! b_timecosts)
+#endif /* HAVE_LIBARGON2 */
+
+       if (! b_pbkdf2_itercounts)
        {
-               b_timecosts = b_timecosts_default;
-               b_timecosts_count = BENCH_ARRAY_SIZE(b_timecosts_default);
+               b_pbkdf2_itercounts = b_pbkdf2_itercounts_default;
+               b_pbkdf2_itercounts_count = BENCH_ARRAY_SIZE(b_pbkdf2_itercounts_default);
        }
-       if (! b_threads)
+       if (! b_pbkdf2_digests)
        {
-               b_threads = b_threads_default;
-               b_threads_count = BENCH_ARRAY_SIZE(b_threads_default);
+               b_pbkdf2_digests = b_pbkdf2_digests_default;
+               b_pbkdf2_digests_count = BENCH_ARRAY_SIZE(b_pbkdf2_digests_default);
        }
-#endif /* HAVE_LIBARGON2 */
 
        return true;
 }
 
 #ifdef HAVE_LIBARGON2
 
-static inline bool ATHEME_FATTR_WUR
-do_argon2_benchmark(const argon2_type type, const size_t memcost, const size_t timecost, const size_t threads)
-{
-       long double elapsed;
-
-       if (! benchmark_argon2(type, memcost, timecost, threads, &elapsed))
-               // This function logs error messages on failure
-               return false;
-
-       (void) fprintf(stderr, "%10s %10zu %8zu %4zu %12LF\n", argon2_type_to_name(type),
-                              memcost, timecost, threads, elapsed);
-       return true;
-}
-
 static bool ATHEME_FATTR_WUR
 do_argon2_benchmarks(void)
 {
@@ -385,33 +425,22 @@ do_argon2_benchmarks(void)
 
        (void) argon2_print_colheaders();
 
-       for (size_t b_type = 0; b_type < b_types_count; b_type++)
-         for (size_t b_memcost = 0; b_memcost < b_memcosts_count; b_memcost++)
-           for (size_t b_timecost = 0; b_timecost < b_timecosts_count; b_timecost++)
-             for (size_t b_thread = 0; b_thread < b_threads_count; b_thread++)
-               if (! do_argon2_benchmark(b_types[b_type], b_memcosts[b_memcost],
-                                         b_timecosts[b_timecost], b_threads[b_thread]))
+       for (size_t b_argon2_type = 0; b_argon2_type < b_argon2_types_count; b_argon2_type++)
+         for (size_t b_argon2_memcost = 0; b_argon2_memcost < b_argon2_memcosts_count; b_argon2_memcost++)
+           for (size_t b_argon2_timecost = 0; b_argon2_timecost < b_argon2_timecosts_count; b_argon2_timecost++)
+             for (size_t b_argon2_thread = 0; b_argon2_thread < b_argon2_threads_count; b_argon2_thread++)
+               if (! benchmark_argon2(b_argon2_types[b_argon2_type], b_argon2_memcosts[b_argon2_memcost],
+                                      b_argon2_timecosts[b_argon2_timecost], b_argon2_threads[b_argon2_thread], NULL))
                  // This function logs error messages on failure
                  return false;
 
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "\n");
        return true;
 }
 
 #endif /* HAVE_LIBARGON2 */
 
-static inline bool ATHEME_FATTR_WUR
-do_pbkdf2_benchmark(const enum digest_algorithm digest, const size_t iterations)
-{
-       long double elapsed;
-
-       if (! benchmark_pbkdf2(digest, iterations, &elapsed))
-               // This function logs error messages on failure
-               return false;
-
-       (void) fprintf(stderr, "%8s %8zu %12LF\n", md_digest_to_name(digest), iterations, elapsed);
-       return true;
-}
-
 static bool ATHEME_FATTR_WUR
 do_pbkdf2_benchmarks(void)
 {
@@ -421,18 +450,22 @@ do_pbkdf2_benchmarks(void)
 
        (void) pbkdf2_print_colheaders();
 
-       for (size_t b_digest = 0; b_digest < b_digests_count; b_digest++)
-         for (size_t b_itercount = 0; b_itercount < b_itercounts_count; b_itercount++)
-           if (! do_pbkdf2_benchmark(b_digests[b_digest], b_itercounts[b_itercount]))
+       for (size_t b_pbkdf2_digest = 0; b_pbkdf2_digest < b_pbkdf2_digests_count; b_pbkdf2_digest++)
+         for (size_t b_pbkdf2_itercount = 0; b_pbkdf2_itercount < b_pbkdf2_itercounts_count; b_pbkdf2_itercount++)
+           if (! benchmark_pbkdf2(b_pbkdf2_digests[b_pbkdf2_digest], b_pbkdf2_itercounts[b_pbkdf2_itercount], NULL))
              // This function logs error messages on failure
              return false;
 
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "\n");
        return true;
 }
 
 int
 main(int argc, char *argv[])
 {
+       (void) print_version();
+
        if (! benchmark_init())
                // This function logs error messages on failure
                return EXIT_FAILURE;
@@ -441,28 +474,28 @@ main(int argc, char *argv[])
                // This function logs error messages on failure
                return EXIT_FAILURE;
 
-       (void) fprintf(stderr, "\n");
-       (void) fprintf(stderr, "%s\n", PACKAGE_STRING);
-       (void) fprintf(stderr, "Using digest frontend: %s\n", digest_get_frontend_info());
-       (void) fprintf(stderr, "\n");
-
 #if (ATHEME_API_DIGEST_FRONTEND == ATHEME_API_DIGEST_FRONTEND_INTERNAL) && !defined(IN_CI_BUILD_ENVIRONMENT)
-       (void) fprintf(stderr, "WARNING: This program will perform significantly better if you build it\n");
-       (void) fprintf(stderr, "         against a supported third-party cryptographic digest library.\n");
        (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "NOTE: This program may perform significantly better if you build it\n");
+       (void) fprintf(stderr, "      against a supported third-party cryptographic digest library!\n");
 #endif
 
-       if (run_optimal_benchmarks && ! do_optimal_benchmarks(optimal_clocklimit, optimal_memlimit))
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "\n");
+
+       if ((run_options & BENCH_RUN_OPTIONS_OPTIMAL) &&
+           ! do_optimal_benchmarks(optimal_clocklimit, optimal_memlimit, optimal_memlimit_given))
                // This function logs error messages on failure
                return EXIT_FAILURE;
 
 #ifdef HAVE_LIBARGON2
-       if (run_argon2_benchmarks && ! do_argon2_benchmarks())
+       if ((run_options & BENCH_RUN_OPTIONS_ARGON2) && ! do_argon2_benchmarks())
                // This function logs error messages on failure
                return EXIT_FAILURE;
 #endif /* HAVE_LIBARGON2 */
 
-       if (run_pbkdf2_benchmarks && ! do_pbkdf2_benchmarks())
+       if ((run_options & BENCH_RUN_OPTIONS_PBKDF2) && ! do_pbkdf2_benchmarks())
                // This function logs error messages on failure
                return EXIT_FAILURE;
 
index 4f7c9552e26ac9332024f68d57a774bce9081f27..d5f08ee87589072b883b10c5766d4fc58e8d8d85 100644 (file)
@@ -9,36 +9,40 @@
  * copyright notice and this permission notice appear in all copies.
  */
 
-#include <atheme/attributes.h>  // ATHEME_FATTR_WUR
-#include <atheme/argon2.h>      // ARGON2_*
-#include <atheme/digest.h>      // DIGALG_*, digest_oneshot_pbkdf2()
-#include <atheme/pbkdf2.h>      // PBKDF2_*
-#include <atheme/stdheaders.h>  // (everything else)
-#include <atheme/sysconf.h>     // HAVE_LIBARGON2
+#include <atheme/attributes.h>      // ATHEME_FATTR_WUR
+#include <atheme/argon2.h>          // ARGON2_*
+#include <atheme/digest.h>          // DIGALG_*, digest_oneshot_pbkdf2()
+#include <atheme/pbkdf2.h>          // PBKDF2_*
+#include <atheme/stdheaders.h>      // (everything else)
+#include <atheme/sysconf.h>         // HAVE_LIBARGON2
 
-#include "benchmark.h"          // benchmark_*()
-#include "optimal.h"            // self-declarations
-#include "utils.h"              // (everything else)
+#ifdef HAVE_LIBARGON2
+#  include <argon2.h>               // argon2_type, argon2_type2string()
+#endif
+
+#include "benchmark.h"              // (everything else)
+#include "optimal.h"                // self-declarations
 
 #ifdef HAVE_LIBARGON2
 
 static bool ATHEME_FATTR_WUR
-do_optimal_argon2_benchmark(const long double clocklimit, const size_t memlimit)
+do_optimal_argon2_benchmark(const long double optimal_clocklimit, const size_t optimal_memlimit)
 {
        (void) fprintf(stderr, "Beginning automatic optimal Argon2 benchmark ...\n");
+       (void) fprintf(stderr, "\n");
        (void) fprintf(stderr, "NOTE: This does not test multithreading. Use '-a -p' for thread testing.\n");
        (void) fprintf(stderr, "\n");
 
        (void) argon2_print_colheaders();
 
-       const argon2_type type = Argon2_id;
-       size_t memcost = memlimit;
-       size_t timecost = ARGON2_TIMECOST_MIN;
-       const size_t threads = 1U;
-
-       bool timecost_raised = false;
        long double elapsed_prev = 0L;
        long double elapsed = 0L;
+       size_t timecost_prev = 0U;
+
+       const argon2_type type = Argon2_id;
+       size_t memcost = optimal_memlimit;
+       size_t timecost = ARGON2_TIMECOST_MIN;
+       const size_t threads = 1ULL;
 
        // First try at our memory limit and the minimum time cost
        if (! benchmark_argon2(type, memcost, timecost, threads, &elapsed))
@@ -46,7 +50,7 @@ do_optimal_argon2_benchmark(const long double clocklimit, const size_t memlimit)
                return false;
 
        // If that's still too slow, halve the memory usage until it isn't
-       while (elapsed > clocklimit)
+       while (elapsed > optimal_clocklimit)
        {
                if (memcost <= ARGON2_MEMCOST_MIN)
                {
@@ -65,22 +69,22 @@ do_optimal_argon2_benchmark(const long double clocklimit, const size_t memlimit)
        }
 
        // Now that it's fast enough, raise the time cost until it isn't
-       while (elapsed <clocklimit)
+       while (elapsed < optimal_clocklimit)
        {
-               timecost++;
-               timecost_raised = true;
                elapsed_prev = elapsed;
+               timecost_prev = timecost;
+               timecost++;
 
                if (! benchmark_argon2(type, memcost, timecost, threads, &elapsed))
                        // This function logs error messages on failure
                        return false;
        }
 
-       // If it was raised, go back to the previous loop's outputs
-       if (timecost_raised)
+       // If it was raised, go back to the previous loop's outputs (now that it's too slow)
+       if (timecost_prev)
        {
-               timecost--;
                elapsed = elapsed_prev;
+               timecost = timecost_prev;
        }
 
        (void) fprintf(stderr, "\n");
@@ -88,13 +92,16 @@ do_optimal_argon2_benchmark(const long double clocklimit, const size_t memlimit)
        (void) fprintf(stderr, "\n");
        (void) fflush(stderr);
        (void) fprintf(stdout, "crypto {\n");
-       (void) fprintf(stdout, "\t/* Target: %LFs; Benchmarked: %LFs */\n", clocklimit, elapsed);
-       (void) fprintf(stdout, "\targon2_type = \"%s\";\n", argon2_type_to_name(type));
-       (void) fprintf(stdout, "\targon2_memcost = %zu; /* %u KiB */ \n", memcost, (1U << memcost));
+       (void) fprintf(stdout, "\t/* Target: %LFs; Benchmarked: %LFs */\n", optimal_clocklimit, elapsed);
+       (void) fprintf(stdout, "\targon2_type = \"%s\";\n", argon2_type2string(type, 0));
+       (void) fprintf(stdout, "\targon2_memcost = %zu; /* %llu KiB */ \n", memcost, (1ULL << memcost));
        (void) fprintf(stdout, "\targon2_timecost = %zu;\n", timecost);
        (void) fprintf(stdout, "\targon2_threads = %zu;\n", threads);
        (void) fprintf(stdout, "};\n");
        (void) fflush(stdout);
+       (void) fsync(fileno(stdout));
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "\n");
        (void) fprintf(stderr, "\n");
        (void) fflush(stderr);
        return true;
@@ -103,13 +110,15 @@ do_optimal_argon2_benchmark(const long double clocklimit, const size_t memlimit)
 #endif /* HAVE_LIBARGON2 */
 
 static bool ATHEME_FATTR_WUR
-do_optimal_pbkdf2_benchmark(const long double clocklimit)
+do_optimal_pbkdf2_benchmark(const long double optimal_clocklimit)
 {
        (void) fprintf(stderr, "Beginning automatic optimal PBKDF2 benchmark ...\n");
+       (void) fprintf(stderr, "\n");
        (void) fprintf(stderr, "NOTE: This does not test SHA1. Use '-k -d' for SHA1 testing.\n");
-       (void) fprintf(stderr, "NOTE: If you wish to support SASL SCRAM logins, please see\n");
-       (void) fprintf(stderr, "      the 'doc/SASL-SCRAM-SHA' file, whose parameter advice\n");
-       (void) fprintf(stderr, "      takes precedence over the advice given here.\n");
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "NOTE: If you wish to support SASL SCRAM logins, please see the\n");
+       (void) fprintf(stderr, "      'doc/SASL-SCRAM-SHA' file in the source code repository, whose parameter\n");
+       (void) fprintf(stderr, "      advice takes precedence over the advice given by this benchmark utility!\n");
        (void) fprintf(stderr, "\n");
 
        (void) pbkdf2_print_colheaders();
@@ -149,12 +158,16 @@ do_optimal_pbkdf2_benchmark(const long double clocklimit)
                elapsed = elapsed_sha512;
        }
 
+       /* PBKDF2 is pretty linear: There's only one parameter (iteration count), and it has
+        * almost perfect scaling on the algorithm's runtime. This enables a very simplified
+        * optimal parameter discovery process, compared to the other functions above.
+        */
        const char *const mdname = md_digest_to_name(md);
-       size_t iterations = (size_t) (initial / (elapsed / clocklimit));
+       size_t iterations = (size_t) (initial * (optimal_clocklimit / elapsed));
        iterations -= (iterations % 1000U);
        iterations = BENCH_MIN(initial, iterations);
 
-       while (elapsed > clocklimit)
+       while (elapsed > optimal_clocklimit)
        {
                if (iterations <= PBKDF2_ITERCNT_MIN)
                {
@@ -177,25 +190,38 @@ do_optimal_pbkdf2_benchmark(const long double clocklimit)
        (void) fprintf(stderr, "\n");
        (void) fflush(stderr);
        (void) fprintf(stdout, "crypto {\n");
-       (void) fprintf(stdout, "\t/* Target: %LFs; Benchmarked: %LFs */\n", clocklimit, elapsed);
+       (void) fprintf(stdout, "\t/* Target: %LFs; Benchmarked: %LFs */\n", optimal_clocklimit, elapsed);
        (void) fprintf(stdout, "\tpbkdf2v2_digest = \"%s\";\n", mdname);
        (void) fprintf(stdout, "\tpbkdf2v2_rounds = %zu;\n", iterations);
        (void) fprintf(stdout, "};\n");
        (void) fflush(stdout);
+       (void) fsync(fileno(stdout));
+       (void) fprintf(stderr, "\n");
+       (void) fprintf(stderr, "\n");
        (void) fprintf(stderr, "\n");
        (void) fflush(stderr);
        return true;
 }
 
 bool ATHEME_FATTR_WUR
-do_optimal_benchmarks(const long double clocklimit, const unsigned int memlimit)
+do_optimal_benchmarks(const long double optimal_clocklimit, const size_t ATHEME_VATTR_MAYBE_UNUSED optimal_memlimit,
+                      const bool ATHEME_VATTR_MAYBE_UNUSED optimal_memlimit_given)
 {
 #ifdef HAVE_LIBARGON2
-       if (! do_optimal_argon2_benchmark(clocklimit, memlimit))
+       if (! optimal_memlimit_given)
+       {
+               (void) fprintf(stderr, "Be sure to specify -L/--optimal-memory-limit appropriately for this machine!\n");
+               (void) fprintf(stderr, "\n");
+               (void) fprintf(stderr, "\n");
+               (void) fprintf(stderr, "\n");
+       }
+
+       if (! do_optimal_argon2_benchmark(optimal_clocklimit, optimal_memlimit))
                // This function logs error messages on failure
                return false;
 #endif
-       if (! do_optimal_pbkdf2_benchmark(clocklimit))
+
+       if (! do_optimal_pbkdf2_benchmark(optimal_clocklimit))
                // This function logs error messages on failure
                return false;
 
index 25e8b0f7a13156e4b9e7de1e6b7f3850281cb2be..4c3712640b57da75aa5931db9e866acb2ed63688 100644 (file)
 #ifndef ATHEME_SRC_CRYPTO_BENCHMARK_OPTIMAL_H
 #define ATHEME_SRC_CRYPTO_BENCHMARK_OPTIMAL_H 1
 
-#define BENCH_MIN(a, b) (((a) <= (b)) ? (a) : (b))
+#include <atheme/attributes.h>      // ATHEME_FATTR_WUR
+#include <atheme/stdheaders.h>      // bool
 
-#include <atheme/attributes.h>  // ATHEME_FATTR_WUR
-#include <atheme/stdheaders.h>  // bool
-
-bool do_optimal_benchmarks(long double, unsigned int) ATHEME_FATTR_WUR;
+bool do_optimal_benchmarks(long double, size_t, bool) ATHEME_FATTR_WUR;
 
 #endif /* !ATHEME_SRC_CRYPTO_BENCHMARK_OPTIMAL_H */
diff --git a/src/crypto-benchmark/utils.c b/src/crypto-benchmark/utils.c
deleted file mode 100644 (file)
index d6cd09b..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * SPDX-License-Identifier: ISC
- * SPDX-URL: https://spdx.org/licenses/ISC.html
- *
- * Copyright (C) 2019 Aaron M. D. Jones <aaronmdjones@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#include <atheme/digest.h>      // DIGALG_*
-#include <atheme/stdheaders.h>  // (everything else)
-#include <atheme/sysconf.h>     // HAVE_LIBARGON2
-
-#include "utils.h"              // self-declarations
-
-#ifdef HAVE_LIBARGON2
-
-const char *
-argon2_type_to_name(const argon2_type b_type)
-{
-       return argon2_type2string(b_type, 0);
-}
-
-argon2_type
-argon2_name_to_type(const char *const restrict b_name)
-{
-       if (strcasecmp(b_name, "Argon2d") == 0)
-               return Argon2_d;
-       else if (strcasecmp(b_name, "Argon2i") == 0)
-               return Argon2_i;
-       else if (strcasecmp(b_name, "Argon2id") == 0)
-               return Argon2_id;
-
-       (void) fprintf(stderr, "%s: '%s' is not a valid type name\n", MOWGLI_FUNC_NAME, b_name);
-       (void) fprintf(stderr, "%s: valid names are: Argon2d, Argon2i, Argon2id\n", MOWGLI_FUNC_NAME);
-
-       exit(EXIT_FAILURE);
-}
-
-void
-argon2_print_colheaders(void)
-{
-       (void) fprintf(stderr, "%-10s %-14s %-10s %-10s %-14s\n",
-                              "Type", "MemCost", "TimeCost", "Threads", "Elapsed");
-       (void) fprintf(stderr, "---------- -------------- ---------- ---------- --------------\n");
-}
-
-void
-argon2_print_rowstats(const argon2_type type, const size_t memcost, const size_t timecost, const size_t threads,
-                      const long double elapsed)
-{
-       (void) fprintf(stderr, "%10s %13uK %10zu %10zu %13LFs\n", argon2_type_to_name(type),
-                              (1U << memcost), timecost, threads, elapsed);
-}
-
-#endif /* HAVE_LIBARGON2 */
-
-const char *
-md_digest_to_name(const enum digest_algorithm b_digest)
-{
-       switch (b_digest)
-       {
-               case DIGALG_MD5:
-                       return "MD5";
-               case DIGALG_SHA1:
-                       return "SHA1";
-               case DIGALG_SHA2_256:
-                       return "SHA256";
-               case DIGALG_SHA2_512:
-                       return "SHA512";
-       }
-
-       return NULL;
-}
-
-enum digest_algorithm
-md_name_to_digest(const char *const restrict b_name)
-{
-       if (strcasecmp(b_name, "MD5") == 0)
-               return DIGALG_MD5;
-       else if (strcasecmp(b_name, "SHA1") == 0)
-               return DIGALG_SHA1;
-       else if (strcasecmp(b_name, "SHA2-256") == 0)
-               return DIGALG_SHA2_256;
-       else if (strcasecmp(b_name, "SHA2-512") == 0)
-               return DIGALG_SHA2_512;
-
-       (void) fprintf(stderr, "%s: '%s' is not a valid algorithm name\n", MOWGLI_FUNC_NAME, b_name);
-       (void) fprintf(stderr, "%s: valid names are: MD5, SHA1, SHA2-256, SHA2-512\n", MOWGLI_FUNC_NAME);
-
-       exit(EXIT_FAILURE);
-}
-
-void
-pbkdf2_print_colheaders(void)
-{
-       (void) fprintf(stderr, "%-10s %-10s %-14s\n", "Digest", "Iterations", "Elapsed");
-       (void) fprintf(stderr, "---------- ---------- --------------\n");
-}
-
-void
-pbkdf2_print_rowstats(const enum digest_algorithm digest, const size_t iterations, const long double elapsed)
-{
-       (void) fprintf(stderr, "%10s %10zu %13LFs\n", md_digest_to_name(digest), iterations, elapsed);
-}
diff --git a/src/crypto-benchmark/utils.h b/src/crypto-benchmark/utils.h
deleted file mode 100644 (file)
index 9434091..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * SPDX-License-Identifier: ISC
- * SPDX-URL: https://spdx.org/licenses/ISC.html
- *
- * Copyright (C) 2019 Aaron M. D. Jones <aaronmdjones@gmail.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- */
-
-#ifndef ATHEME_SRC_CRYPTO_BENCHMARK_UTILS_H
-#define ATHEME_SRC_CRYPTO_BENCHMARK_UTILS_H 1
-
-#include <atheme/digest.h>      // enum digest_algorithm
-#include <atheme/sysconf.h>     // HAVE_LIBARGON2
-
-#ifdef HAVE_LIBARGON2
-#  include <argon2.h>           // argon2_type
-#endif
-
-#ifdef HAVE_LIBARGON2
-argon2_type argon2_name_to_type(const char *);
-const char *argon2_type_to_name(argon2_type);
-void argon2_print_colheaders(void);
-void argon2_print_rowstats(argon2_type, size_t, size_t, size_t, long double);
-#endif
-
-enum digest_algorithm md_name_to_digest(const char *);
-const char *md_digest_to_name(enum digest_algorithm);
-void pbkdf2_print_colheaders(void);
-void pbkdf2_print_rowstats(enum digest_algorithm, size_t, long double);
-
-#endif /* !ATHEME_SRC_CRYPTO_BENCHMARK_UTILS_H */