Skip to content

Commit

Permalink
Add DH_check support to perf tool
Browse files Browse the repository at this point in the history
  • Loading branch information
torben-hansen committed Apr 26, 2023
1 parent 9a53f1e commit acebcf7
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions tool/bssl_bm.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "openssl/ctrdrbg.h"
#include <openssl/curve25519.h>
#include <openssl/crypto.h>
#include <openssl/dh.h>
#include <openssl/digest.h>
#include <openssl/err.h>
#include <openssl/ec.h>
Expand Down
1 change: 1 addition & 0 deletions tool/ossl_bm.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <openssl/aes.h>
#include <openssl/bn.h>
#include <openssl/crypto.h>
#include <openssl/dh.h>
#include <openssl/ec.h>
#include <openssl/err.h>
#include <openssl/evp.h>
Expand Down
121 changes: 120 additions & 1 deletion tool/speed.cc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,13 @@ static std::string ChunkLenSuffix(size_t chunk_len) {
return buf;
}

static std::string PrimeLenSuffix(size_t prime_length) {
char buf[32];
snprintf(buf, sizeof(buf), " (%zu bit%s)", prime_length,
prime_length != 1 ? "s" : "");
return buf;
}

// TimeResults represents the results of benchmarking a function.
struct TimeResults {
// num_calls is the number of function calls done in the time period.
Expand Down Expand Up @@ -113,6 +120,19 @@ struct TimeResults {
}
}

void PrintWithPrimes(const std::string &description,
size_t prime_size) const {
if (g_print_json) {
PrintJSON(description, "primeSizePerCall", prime_size);
} else {
printf(
"Did %" PRIu64 " %s operations in %" PRIu64
"us (%.3f ops/sec)\n",
num_calls, (description + PrimeLenSuffix(prime_size)).c_str(), us,
(static_cast<double>(num_calls) / static_cast<double>(us)) * 1000000);
}
}

private:
void PrintJSON(const std::string &description,
size_t bytes_per_call = 0) const {
Expand All @@ -132,6 +152,25 @@ struct TimeResults {
first_json_printed = true;
}

void PrintJSON(const std::string &description,
const std::string &size_label,
size_t size = 0) const {
if (first_json_printed) {
puts(",");
}

printf("{\"description\": \"%s\", \"numCalls\": %" PRIu64
", \"microseconds\": %" PRIu64,
description.c_str(), num_calls, us);

if (size > 0) {
printf(", \"%s\": %zu", size_label.c_str(), size);
}

printf("}");
first_json_printed = true;
}

// first_json_printed is true if |g_print_json| is true and the first item in
// the JSON results has been printed already. This is used to handle the
// commas between each item in the result list.
Expand Down Expand Up @@ -167,6 +206,7 @@ static uint64_t time_now() {

static uint64_t g_timeout_seconds = 1;
static std::vector<size_t> g_chunk_lengths = {16, 256, 1350, 8192, 16384};
static std::vector<size_t> g_prime_bit_lengths = {2048, 3072};

static bool TimeFunction(TimeResults *results, std::function<bool()> func) {
// The first time |func| is called an expensive self check might run that
Expand Down Expand Up @@ -1892,6 +1932,52 @@ static bool SpeedJitter(std::string selected) {
}
#endif

static bool SpeedDHcheck(size_t prime_bit_length) {

TimeResults results;
bssl::UniquePtr<DH> dh_params(DH_new());
if (dh_params == nullptr) {
return false;
}

// DH_generate_parameters_ex grows exponentially slower as prime length grows.
if (DH_generate_parameters_ex(dh_params.get(), prime_bit_length,
DH_GENERATOR_2, nullptr) != 1) {
return false;
}

if (!TimeFunction(&results, [&dh_params]() -> bool {
int result = 0;
if (DH_check(dh_params.get(), &result) != 1) {
return false;
}
return true;
})) {
return false;
}

results.PrintWithPrimes("DH check(s)", prime_bit_length);
return true;
}

static bool SpeedDHcheck(std::string selected) {
if (!selected.empty() && selected.find("dhcheck") == std::string::npos) {
return true;
}

if (!g_print_json) {
printf("DH check speed test is very slow. Speed test works best with higher timeouts.\n");
}

for (size_t prime_bit_length : g_prime_bit_lengths) {
if (!SpeedDHcheck(prime_bit_length)) {
return false;
}
}

return true;
}

#if !defined(OPENSSL_BENCHMARK) && !defined(BORINGSSL_BENCHMARK)
static bool SpeedPKCS8(const std::string &selected) {
if (!selected.empty() && selected.find("pkcs8") == std::string::npos) {
Expand Down Expand Up @@ -2004,6 +2090,12 @@ static const argument_t kArguments[] = {
"A comma-separated list of input sizes to run tests at (default is "
"16,256,1350,8192,16384)",
},
{
"-primes",
kOptionalArgument,
"A comma-separated list of prime input sizes (bits) to run tests at "
"(default is 2048,3072)",
},
{
"-json",
kBooleanArgument,
Expand Down Expand Up @@ -2072,6 +2164,32 @@ bool Speed(const std::vector<std::string> &args) {
}
}

if (args_map.count("-primes") != 0) {
g_prime_bit_lengths.clear();
const char *start = args_map["-primes"].data();
const char *end = start + args_map["-primes"].size();
while (start != end) {
errno = 0;
char *ptr;
unsigned long long val = strtoull(start, &ptr, 10);
if (ptr == start /* no numeric characters found */ ||
errno == ERANGE /* overflow */ ||
static_cast<size_t>(val) != val) {
fprintf(stderr, "Error parsing -primes argument\n");
return false;
}
g_prime_bit_lengths.push_back(static_cast<size_t>(val));
start = ptr;
if (start != end) {
if (*start != ',') {
fprintf(stderr, "Error parsing -primes argument\n");
return false;
}
start++;
}
}
}

// kTLSADLen is the number of bytes of additional data that TLS passes to
// AEADs.
static const size_t kTLSADLen = 13;
Expand Down Expand Up @@ -2172,8 +2290,9 @@ bool Speed(const std::vector<std::string> &args) {
!SpeedPKCS8(selected) ||
#endif
!SpeedBase64(selected) ||
!SpeedSipHash(selected)
!SpeedSipHash(selected) ||
#endif
!SpeedDHcheck(selected)
) {
return false;
}
Expand Down

0 comments on commit acebcf7

Please sign in to comment.