Skip to content

Instantly share code, notes, and snippets.

@raycoll
Created May 1, 2021 15:55
Show Gist options
  • Save raycoll/cf89b622387056083df3a6fcc6e6a12d to your computer and use it in GitHub Desktop.
Save raycoll/cf89b622387056083df3a6fcc6e6a12d to your computer and use it in GitHub Desktop.
ecdhe + ec_key_check_key microbenchmark
#include <openssl/opensslv.h>
#include <openssl/ecdh.h>
#include <openssl/evp.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdint.h>
#include <sys/utsname.h>
#include <time.h>
struct curve_testcase
{
int nid;
const char *name;
};
const struct curve_testcase testcases[] = {
{ .nid = NID_X9_62_prime256v1, .name = "secp256r1" },
{ .nid = NID_secp384r1, .name = "secp384r1" },
{ .nid = NID_secp521r1, .name = "secp521r1" },
// too lazy to write the conditional to support the keygen implementation for this curve.
//{ .nid = NID_X25519, .name = "x25519" },
};
const int NUM_ITERS=10000;
const unsigned int USECS_IN_SEC=1000000;
static void print_summary(const struct curve_testcase *testcase, double avg_usecs_keygen, double avg_usecs_key_check)
{
printf("%s: %f avg usecs for ECDH key generation %f avg usecs for EC_KEY_check_key in %d iterations \n", testcase->name, avg_usecs_keygen, avg_usecs_key_check, NUM_ITERS);
}
static void microbenchmark_ec_key_check_key(const struct curve_testcase *testcase)
{
double usecs_elapsed_keygen = 0;
double usecs_elapsed_key_check = 0;
for (int i = 0; i < NUM_ITERS; i++) {
// Benchmark the ephemeral key generation for the curve
double begin = clock();
EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL);
EVP_PKEY_paramgen_init(pctx);
EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, testcase->nid);
EVP_PKEY *params = NULL;
EVP_PKEY_paramgen(pctx, &params);
EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new(params, NULL);
EVP_PKEY_keygen_init(kctx);
EVP_PKEY *pkey = NULL;
EVP_PKEY_keygen(kctx, &pkey);
EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
double end = clock();
usecs_elapsed_keygen += ((end - begin) / CLOCKS_PER_SEC) * USECS_IN_SEC;
// Benchmark key check for the curve.
begin = clock();
const int rc = EC_KEY_check_key(ec_key);
end = clock();
usecs_elapsed_key_check += ((end - begin) / CLOCKS_PER_SEC) * USECS_IN_SEC;
EVP_PKEY_free(params);
EVP_PKEY_CTX_free(kctx);
EVP_PKEY_free(pkey);
}
print_summary(testcase, (double) usecs_elapsed_keygen / (double) NUM_ITERS, (double) usecs_elapsed_key_check / (double)
NUM_ITERS);
}
int main(void)
{
struct utsname name;
uname(&name);
printf("starting ECC microbenchmark. Platform: %s %s, Openssl version: %s\n",
name.sysname,
name.machine,
OPENSSL_VERSION_TEXT);
for (int i = 0; i < (sizeof(testcases) / sizeof(testcases[0])) ;
i++) {
microbenchmark_ec_key_check_key(&testcases[i]);
}
}
@ttjsu-aws
Copy link

Note: EC_KEY_check_key validation check is unnecessary for Curve x25519, so the line 20-21 can be safely removed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment