diff --git a/tool/speed.cc b/tool/speed.cc index f4b452fc..9f5259f5 100644 --- a/tool/speed.cc +++ b/tool/speed.cc @@ -12,11 +12,13 @@ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include #include +#include #include #include #include @@ -194,6 +196,59 @@ static bool SpeedRSA(const std::string &key_name, RSA *key, return true; } +static bool SpeedRSAKeyGen(const std::string &selected) { + // Don't run this by default because it's so slow. + if (selected != "RSAKeyGen") { + return true; + } + + bssl::UniquePtr e(BN_new()); + if (!BN_set_word(e.get(), 65537)) { + return false; + } + + const std::vector kSizes = {2048, 3072, 4096}; + for (int size : kSizes) { + const uint64_t start = time_now(); + unsigned num_calls = 0; + unsigned us; + std::vector durations; + + for (;;) { + bssl::UniquePtr rsa(RSA_new()); + + const uint64_t iteration_start = time_now(); + if (!RSA_generate_key_ex(rsa.get(), size, e.get(), nullptr)) { + fprintf(stderr, "RSA_generate_key_ex failed.\n"); + ERR_print_errors_fp(stderr); + return false; + } + const uint64_t iteration_end = time_now(); + + num_calls++; + durations.push_back(iteration_end - iteration_start); + + us = iteration_end - start; + if (us > 30 * 1000000 /* 30 secs */) { + break; + } + } + + std::sort(durations.begin(), durations.end()); + printf("Did %u RSA %d key-gen operations in %uus (%.1f ops/sec)\n", + num_calls, size, us, + (static_cast(num_calls) / us) * 1000000); + const size_t n = durations.size(); + assert(n > 0); + unsigned median = n & 1 ? durations[n / 2] + : (durations[n / 2 - 1] + durations[n / 2]) / 2; + printf(" min: %uus, median: %uus, max: %uus\n", durations[0], median, + durations[n - 1]); + } + + return true; +} + static uint8_t *align(uint8_t *in, unsigned alignment) { return reinterpret_cast( (reinterpret_cast(in) + alignment) & @@ -719,7 +774,8 @@ bool Speed(const std::vector &args) { !SpeedECDSA(selected) || !Speed25519(selected) || !SpeedSPAKE2(selected) || - !SpeedScrypt(selected)) { + !SpeedScrypt(selected) || + !SpeedRSAKeyGen(selected)) { return false; }