From 814ef81f3e7fc1744717c0de4deaf1c916dfad4f Mon Sep 17 00:00:00 2001 From: jsing <> Date: Sun, 3 Aug 2025 08:29:39 +0000 Subject: Provide benchmarks for EC arithmetic. This provides benchmarking for EC_POINT_add(), EC_POINT_dbl() and EC_POINT_mul()'s scalar * generator path. --- src/regress/lib/libcrypto/ec/Makefile | 3 +- src/regress/lib/libcrypto/ec/ec_arithmetic.c | 210 +++++++++++++++++++++++++++ 2 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 src/regress/lib/libcrypto/ec/ec_arithmetic.c (limited to 'src') diff --git a/src/regress/lib/libcrypto/ec/Makefile b/src/regress/lib/libcrypto/ec/Makefile index 3595a88608..1d976c77d0 100644 --- a/src/regress/lib/libcrypto/ec/Makefile +++ b/src/regress/lib/libcrypto/ec/Makefile @@ -1,4 +1,4 @@ -# $OpenBSD: Makefile,v 1.12 2025/07/23 07:43:14 tb Exp $ +# $OpenBSD: Makefile,v 1.13 2025/08/03 08:29:39 jsing Exp $ .ifdef EOPENSSL35 LDADD += -Wl,-rpath,/usr/local/lib/eopenssl35 -L/usr/local/lib/eopenssl35 @@ -7,6 +7,7 @@ CFLAGS += -DOPENSSL_SUPPRESS_DEPRECATED .endif PROGS += ectest +PROGS += ec_arithmetic PROGS += ec_asn1_test PROGS += ec_point_conversion diff --git a/src/regress/lib/libcrypto/ec/ec_arithmetic.c b/src/regress/lib/libcrypto/ec/ec_arithmetic.c new file mode 100644 index 0000000000..c6f7cd4f8c --- /dev/null +++ b/src/regress/lib/libcrypto/ec/ec_arithmetic.c @@ -0,0 +1,210 @@ +/* $OpenBSD: ec_arithmetic.c,v 1.1 2025/08/03 08:29:39 jsing Exp $ */ +/* + * Copyright (c) 2022,2025 Joel Sing + * + * Permission to use, copy, modify, and 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. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION 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 +#include + +static void +benchmark_ec_point_add(const EC_GROUP *group, EC_POINT *result, + const BIGNUM *scalar, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) +{ + if (!EC_POINT_add(group, result, a, b, ctx)) + errx(1, "EC_POINT_add"); +} + +static void +benchmark_ec_point_dbl(const EC_GROUP *group, EC_POINT *result, + const BIGNUM *scalar, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) +{ + if (!EC_POINT_dbl(group, result, a, ctx)) + errx(1, "EC_POINT_dbl"); +} + +static void +benchmark_ec_point_mul_generator(const EC_GROUP *group, EC_POINT *result, + const BIGNUM *scalar, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx) +{ + if (!EC_POINT_mul(group, result, scalar, NULL, NULL, ctx)) + errx(1, "EC_POINT_mul"); +} + +struct benchmark { + int curve; + const char *desc; + void (*func)(const EC_GROUP *, EC_POINT *, const BIGNUM *, + const EC_POINT *, const EC_POINT *, BN_CTX *); +}; + +static const struct benchmark benchmarks[] = { + { + .curve = NID_X9_62_prime256v1, + .desc = "EC_POINT_add() p256", + .func = benchmark_ec_point_add, + }, + { + .curve = NID_secp384r1, + .desc = "EC_POINT_add() p384", + .func = benchmark_ec_point_add, + }, + { + .curve = NID_secp521r1, + .desc = "EC_POINT_add() p521", + .func = benchmark_ec_point_add, + }, + { + .curve = NID_X9_62_prime256v1, + .desc = "EC_POINT_dbl() p256", + .func = benchmark_ec_point_dbl, + }, + { + .curve = NID_secp384r1, + .desc = "EC_POINT_dbl() p384", + .func = benchmark_ec_point_dbl, + }, + { + .curve = NID_secp521r1, + .desc = "EC_POINT_dbl() p521", + .func = benchmark_ec_point_dbl, + }, + { + .curve = NID_X9_62_prime256v1, + .desc = "EC_POINT_mul() generator p256", + .func = benchmark_ec_point_mul_generator, + }, + { + .curve = NID_secp384r1, + .desc = "EC_POINT_mul() generator p384", + .func = benchmark_ec_point_mul_generator, + }, + { + .curve = NID_secp521r1, + .desc = "EC_POINT_mul() generator p521", + .func = benchmark_ec_point_mul_generator, + }, +}; + +#define N_BENCHMARKS (sizeof(benchmarks) / sizeof(benchmarks[0])) + +static volatile sig_atomic_t benchmark_stop; + +static void +benchmark_sig_alarm(int sig) +{ + benchmark_stop = 1; +} + +static void +benchmark_run(const struct benchmark *bm, int seconds) +{ + struct timespec start, end, duration; + EC_GROUP *group = NULL; + EC_POINT *a = NULL, *b = NULL, *result = NULL; + BIGNUM *order = NULL, *scalar = NULL; + BN_CTX *ctx = NULL; + int i; + + signal(SIGALRM, benchmark_sig_alarm); + + if ((ctx = BN_CTX_new()) == NULL) + errx(1, "BN_CTX_new"); + + if ((group = EC_GROUP_new_by_curve_name(bm->curve)) == NULL) + errx(1, "EC_GROUP_new_by_curve_name"); + if ((order = BN_new()) == NULL) + errx(1, "BN_new"); + if (!EC_GROUP_get_order(group, order, ctx)) + errx(1, "EC_GROUP_get_order"); + + if ((scalar = BN_new()) == NULL) + errx(1, "BN_new"); + if (!BN_rand_range(scalar, order)) + errx(1, "BN_rand_range"); + if (!BN_set_bit(scalar, EC_GROUP_order_bits(group) - 1)) + errx(1, "BN_set_bit"); + + if ((result = EC_POINT_new(group)) == NULL) + errx(1, "EC_POINT_new"); + if ((a = EC_POINT_new(group)) == NULL) + errx(1, "EC_POINT_new"); + if ((b = EC_POINT_new(group)) == NULL) + errx(1, "EC_POINT_new"); + + if (!EC_POINT_mul(group, a, scalar, NULL, NULL, ctx)) + errx(1, "EC_POINT_mul"); + if (!EC_POINT_mul(group, b, scalar, NULL, NULL, ctx)) + errx(1, "EC_POINT_mul"); + + benchmark_stop = 0; + i = 0; + alarm(seconds); + + clock_gettime(CLOCK_MONOTONIC, &start); + + fprintf(stderr, "Benchmarking %s for %ds: ", bm->desc, seconds); + while (!benchmark_stop) { + bm->func(group, result, scalar, a, b, ctx); + i++; + } + clock_gettime(CLOCK_MONOTONIC, &end); + timespecsub(&end, &start, &duration); + fprintf(stderr, "%d iterations in %f seconds\n", i, + duration.tv_sec + duration.tv_nsec / 1000000000.0); + + EC_GROUP_free(group); + EC_POINT_free(result); + EC_POINT_free(a); + EC_POINT_free(b); + BN_free(order); + BN_free(scalar); + BN_CTX_free(ctx); +} + +static void +benchmark_ec_mul_single(void) +{ + const struct benchmark *bm; + size_t i; + + for (i = 0; i < N_BENCHMARKS; i++) { + bm = &benchmarks[i]; + benchmark_run(bm, 5); + } +} + +int +main(int argc, char **argv) +{ + int benchmark = 0, failed = 0; + + if (argc == 2 && strcmp(argv[1], "--benchmark") == 0) + benchmark = 1; + + if (benchmark && !failed) + benchmark_ec_mul_single(); + + return failed; +} -- cgit v1.2.3-55-g6feb