summaryrefslogtreecommitdiff
path: root/src/usr.bin/openssl
diff options
context:
space:
mode:
authorkenjiro <>2026-03-18 21:50:24 +0000
committerkenjiro <>2026-03-18 21:50:24 +0000
commit82f203504202bf0d907e6a786382a70909be7a4f (patch)
treef5c5ef338bc20a8eff13675f09785eaf74aa363a /src/usr.bin/openssl
parent80318abdaa00a71f2fb14771bf4222c73b975fff (diff)
downloadopenbsd-82f203504202bf0d907e6a786382a70909be7a4f.tar.gz
openbsd-82f203504202bf0d907e6a786382a70909be7a4f.tar.bz2
openbsd-82f203504202bf0d907e6a786382a70909be7a4f.zip
openssl speed: add benchmarking support for ML-KEM
Add support for benchmarking ML-KEM key encapsulation mechanisms to openssl speed. The following operations are measured: - key generation - encapsulation - decapsulation Two parameter sets are supported: mlkem768 mlkem1024 The benchmark can be invoked using the following options: mlkem run all ML-KEM benchmarks mlkem768 run ML-KEM-768 benchmarks mlkem1024 run ML-KEM-1024 benchmarks Results are reported similarly to other public key algorithms, showing time per operation and operations per second. Machine-readable output (-mr) support is also added for ML-KEM. ok tb
Diffstat (limited to 'src/usr.bin/openssl')
-rw-r--r--src/usr.bin/openssl/speed.c181
1 files changed, 179 insertions, 2 deletions
diff --git a/src/usr.bin/openssl/speed.c b/src/usr.bin/openssl/speed.c
index 1ece133f2e..8c0f0adca7 100644
--- a/src/usr.bin/openssl/speed.c
+++ b/src/usr.bin/openssl/speed.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: speed.c,v 1.50 2025/12/13 01:58:53 kenjiro Exp $ */ 1/* $OpenBSD: speed.c,v 1.51 2026/03/18 21:50:24 kenjiro Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -78,6 +78,7 @@
78#define DSA_SECONDS 10 78#define DSA_SECONDS 10
79#define ECDSA_SECONDS 10 79#define ECDSA_SECONDS 10
80#define ECDH_SECONDS 10 80#define ECDH_SECONDS 10
81#define MLKEM_SECONDS 10
81 82
82#define MAX_UNALIGN 16 83#define MAX_UNALIGN 16
83 84
@@ -95,6 +96,7 @@
95#include <openssl/crypto.h> 96#include <openssl/crypto.h>
96#include <openssl/err.h> 97#include <openssl/err.h>
97#include <openssl/evp.h> 98#include <openssl/evp.h>
99#include <openssl/mlkem.h>
98#include <openssl/modes.h> 100#include <openssl/modes.h>
99#include <openssl/objects.h> 101#include <openssl/objects.h>
100#include <openssl/x509.h> 102#include <openssl/x509.h>
@@ -214,6 +216,12 @@ enum {
214 EC_NUM, 216 EC_NUM,
215}; 217};
216 218
219enum {
220 R_MLKEM_768,
221 R_MLKEM_1024,
222 MLKEM_NUM,
223};
224
217static const char *names[ALGOR_NUM] = { 225static const char *names[ALGOR_NUM] = {
218 "md4", "md5", "hmac(sha256)", "sha1", "rmd160", 226 "md4", "md5", "hmac(sha256)", "sha1", "rmd160",
219 "rc4", "des cbc", "des ede3", "idea cbc", 227 "rc4", "des cbc", "des ede3", "idea cbc",
@@ -230,6 +238,18 @@ static double rsa_results[RSA_NUM][2];
230static double dsa_results[DSA_NUM][2]; 238static double dsa_results[DSA_NUM][2];
231static double ecdsa_results[EC_NUM][2]; 239static double ecdsa_results[EC_NUM][2];
232static double ecdh_results[EC_NUM][1]; 240static double ecdh_results[EC_NUM][1];
241static double mlkem_results[MLKEM_NUM][3];
242
243struct mlkem_speed_param {
244 const char *name;
245 int bits;
246 int rank;
247};
248
249static const struct mlkem_speed_param mlkem_params[MLKEM_NUM] = {
250 [R_MLKEM_768] = { "mlkem768", 768, MLKEM768_RANK },
251 [R_MLKEM_1024] = { "mlkem1024", 1024, MLKEM1024_RANK },
252};
233 253
234static void sig_done(int sig); 254static void sig_done(int sig);
235 255
@@ -1084,6 +1104,7 @@ speed_main(int argc, char **argv)
1084 int dsa_doit[DSA_NUM]; 1104 int dsa_doit[DSA_NUM];
1085 int ecdsa_doit[EC_NUM]; 1105 int ecdsa_doit[EC_NUM];
1086 int ecdh_doit[EC_NUM]; 1106 int ecdh_doit[EC_NUM];
1107 int mlkem_doit[MLKEM_NUM];
1087 int doit[ALGOR_NUM]; 1108 int doit[ALGOR_NUM];
1088 int pr_header = 0; 1109 int pr_header = 0;
1089 const EVP_CIPHER *evp_cipher = NULL; 1110 const EVP_CIPHER *evp_cipher = NULL;
@@ -1134,6 +1155,8 @@ speed_main(int argc, char **argv)
1134 ecdsa_doit[i] = 0; 1155 ecdsa_doit[i] = 0;
1135 for (i = 0; i < EC_NUM; i++) 1156 for (i = 0; i < EC_NUM; i++)
1136 ecdh_doit[i] = 0; 1157 ecdh_doit[i] = 0;
1158 for (i = 0; i < MLKEM_NUM; i++)
1159 mlkem_doit[i] = 0;
1137 1160
1138 1161
1139 j = 0; 1162 j = 0;
@@ -1394,6 +1417,13 @@ speed_main(int argc, char **argv)
1394 else if (strcmp(*argv, "ecdh") == 0) { 1417 else if (strcmp(*argv, "ecdh") == 0) {
1395 for (i = 0; i < EC_NUM; i++) 1418 for (i = 0; i < EC_NUM; i++)
1396 ecdh_doit[i] = 1; 1419 ecdh_doit[i] = 1;
1420 } else if (strcmp(*argv, "mlkem") == 0) {
1421 mlkem_doit[R_MLKEM_768] = 1;
1422 mlkem_doit[R_MLKEM_1024] = 1;
1423 } else if (strcmp(*argv, "mlkem768") == 0) {
1424 mlkem_doit[R_MLKEM_768] = 2;
1425 } else if (strcmp(*argv, "mlkem1024") == 0) {
1426 mlkem_doit[R_MLKEM_1024] = 2;
1397 } else { 1427 } else {
1398 BIO_printf(bio_err, "Error: bad option or value\n"); 1428 BIO_printf(bio_err, "Error: bad option or value\n");
1399 BIO_printf(bio_err, "\n"); 1429 BIO_printf(bio_err, "\n");
@@ -1459,6 +1489,7 @@ speed_main(int argc, char **argv)
1459 BIO_printf(bio_err, "dsa512 dsa1024 dsa2048\n"); 1489 BIO_printf(bio_err, "dsa512 dsa1024 dsa2048\n");
1460 BIO_printf(bio_err, "ecdsap224 ecdsap256 ecdsap384 ecdsap521\n"); 1490 BIO_printf(bio_err, "ecdsap224 ecdsap256 ecdsap384 ecdsap521\n");
1461 BIO_printf(bio_err, "ecdhp224 ecdhp256 ecdhp384 ecdhp521\n"); 1491 BIO_printf(bio_err, "ecdhp224 ecdhp256 ecdhp384 ecdhp521\n");
1492 BIO_printf(bio_err, "mlkem768 mlkem1024\n");
1462 1493
1463#ifndef OPENSSL_NO_IDEA 1494#ifndef OPENSSL_NO_IDEA
1464 BIO_printf(bio_err, "idea "); 1495 BIO_printf(bio_err, "idea ");
@@ -1476,6 +1507,7 @@ speed_main(int argc, char **argv)
1476 BIO_printf(bio_err, "camellia "); 1507 BIO_printf(bio_err, "camellia ");
1477#endif 1508#endif
1478 BIO_printf(bio_err, "rsa "); 1509 BIO_printf(bio_err, "rsa ");
1510 BIO_printf(bio_err, "mlkem ");
1479#ifndef OPENSSL_NO_BF 1511#ifndef OPENSSL_NO_BF
1480 BIO_printf(bio_err, "blowfish"); 1512 BIO_printf(bio_err, "blowfish");
1481#endif 1513#endif
@@ -1517,6 +1549,8 @@ speed_main(int argc, char **argv)
1517 ecdsa_doit[i] = 1; 1549 ecdsa_doit[i] = 1;
1518 for (i = 0; i < EC_NUM; i++) 1550 for (i = 0; i < EC_NUM; i++)
1519 ecdh_doit[i] = 1; 1551 ecdh_doit[i] = 1;
1552 for (i = 0; i < MLKEM_NUM; i++)
1553 mlkem_doit[i] = 1;
1520 } 1554 }
1521 for (i = 0; i < ALGOR_NUM; i++) 1555 for (i = 0; i < ALGOR_NUM; i++)
1522 if (doit[i]) 1556 if (doit[i])
@@ -2362,7 +2396,124 @@ speed_main(int argc, char **argv)
2362 ecdh_doit[j] = 0; 2396 ecdh_doit[j] = 0;
2363 } 2397 }
2364 } 2398 }
2365show_res: 2399
2400 for (j = 0; j < MLKEM_NUM; j++) {
2401 const struct mlkem_speed_param *p = &mlkem_params[j];
2402 int rank = p->rank;
2403 int bits = p->bits;
2404 MLKEM_private_key *priv = NULL;
2405 MLKEM_public_key *pub = NULL;
2406 uint8_t *encoded_pub = NULL;
2407 size_t encoded_pub_len = 0;
2408 uint8_t *ct = NULL, *ss = NULL;
2409 size_t ct_len = 0, ss_len = 0;
2410
2411 if (!mlkem_doit[j])
2412 continue;
2413
2414 pkey_print_message("keygen", "mlkem", bits, MLKEM_SECONDS);
2415 time_f(START);
2416 for (count = 0, run = 1; COND; count++) {
2417 /*
2418 * MLKEM_generate_key requires an uninitialized key
2419 * object, so allocate and free on every iteration.
2420 */
2421 if ((priv = MLKEM_private_key_new(rank)) == NULL)
2422 break;
2423 if (!MLKEM_generate_key(priv, &encoded_pub,
2424 &encoded_pub_len, NULL, NULL)) {
2425 MLKEM_private_key_free(priv);
2426 priv = NULL;
2427 break;
2428 }
2429 MLKEM_private_key_free(priv);
2430 priv = NULL;
2431 free(encoded_pub);
2432 encoded_pub = NULL;
2433 }
2434 d = time_f(STOP);
2435 if (run)
2436 goto mlkem_err;
2437 BIO_printf(bio_err, mr ? "+R8:%ld:%d:%.2f\n"
2438 : "%ld %d-bit ML-KEM keygen in %.2fs\n", count, bits, d);
2439 mlkem_results[j][2] = d / (double)count;
2440 rsa_count = count;
2441
2442 if ((priv = MLKEM_private_key_new(rank)) == NULL ||
2443 (pub = MLKEM_public_key_new(rank)) == NULL)
2444 goto mlkem_err;
2445 if (!MLKEM_generate_key(priv, &encoded_pub, &encoded_pub_len,
2446 NULL, NULL) ||
2447 !MLKEM_parse_public_key(pub, encoded_pub, encoded_pub_len))
2448 goto mlkem_err;
2449 free(encoded_pub);
2450 encoded_pub = NULL;
2451
2452 pkey_print_message("encap", "mlkem", bits, MLKEM_SECONDS);
2453 time_f(START);
2454 for (count = 0, run = 1; COND; count++) {
2455 if (!MLKEM_encap(pub, &ct, &ct_len, &ss,
2456 &ss_len))
2457 break;
2458 free(ct);
2459 ct = NULL;
2460 free(ss);
2461 ss = NULL;
2462 }
2463 d = time_f(STOP);
2464 if (run)
2465 goto mlkem_err;
2466 BIO_printf(bio_err, mr ? "+R9:%ld:%d:%.2f\n"
2467 : "%ld %d-bit ML-KEM encap in %.2fs\n", count, bits, d);
2468 mlkem_results[j][0] = d / (double)count;
2469 rsa_count = count;
2470
2471 if (!MLKEM_encap(pub, &ct, &ct_len, &ss, &ss_len))
2472 goto mlkem_err;
2473 free(ss);
2474 ss = NULL;
2475
2476 pkey_print_message("decap", "mlkem", bits, MLKEM_SECONDS);
2477 time_f(START);
2478 for (count = 0, run = 1; COND; count++) {
2479 if (!MLKEM_decap(priv, ct, ct_len, &ss, &ss_len))
2480 break;
2481 free(ss);
2482 ss = NULL;
2483 }
2484 d = time_f(STOP);
2485 if (run)
2486 goto mlkem_err;
2487 BIO_printf(bio_err, mr ? "+R10:%ld:%d:%.2f\n"
2488 : "%ld %d-bit ML-KEM decap in %.2fs\n", count, bits, d);
2489 mlkem_results[j][1] = d / (double)count;
2490 rsa_count = count;
2491
2492 free(ct);
2493 ct = NULL;
2494 MLKEM_private_key_free(priv);
2495 priv = NULL;
2496 MLKEM_public_key_free(pub);
2497 pub = NULL;
2498
2499 if (rsa_count <= 1) {
2500 /* if longer than 10s, don't do any more */
2501 for (j++; j < MLKEM_NUM; j++)
2502 mlkem_doit[j] = 0;
2503 }
2504 continue;
2505
2506 mlkem_err:
2507 BIO_printf(bio_err, "MLKEM failure\n");
2508 ERR_print_errors(bio_err);
2509 MLKEM_private_key_free(priv);
2510 MLKEM_public_key_free(pub);
2511 free(encoded_pub);
2512 free(ct);
2513 free(ss);
2514 }
2515
2516 show_res:
2366 if (!mr) { 2517 if (!mr) {
2367 fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_VERSION)); 2518 fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_VERSION));
2368 fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_BUILT_ON)); 2519 fprintf(stdout, "%s\n", SSLeay_version(SSLEAY_BUILT_ON));
@@ -2469,6 +2620,32 @@ show_res:
2469 ecdh_results[k][0], 1.0 / ecdh_results[k][0]); 2620 ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
2470 } 2621 }
2471 2622
2623 j = 1;
2624 for (k = 0; k < MLKEM_NUM; k++) {
2625 if (!mlkem_doit[k])
2626 continue;
2627 if (j && !mr) {
2628 printf("%-9s%12s%9s%12s%9s%12s%9s\n",
2629 "", "keygen", "keygen/s",
2630 "encap", "encap/s",
2631 "decap", "decap/s");
2632 j = 0;
2633 }
2634 if (mr)
2635 fprintf(stdout, "+F6:%u:%f:%f:%f:%f:%f:%f\n",
2636 mlkem_params[k].bits,
2637 mlkem_results[k][2], 1.0 / mlkem_results[k][2],
2638 mlkem_results[k][0], 1.0 / mlkem_results[k][0],
2639 mlkem_results[k][1], 1.0 / mlkem_results[k][1]);
2640 else
2641 fprintf(stdout,
2642 "mlkem%4d %10.6fs %8.1f %10.6fs %8.1f %10.6fs %8.1f\n",
2643 mlkem_params[k].bits,
2644 mlkem_results[k][2], 1.0 / mlkem_results[k][2],
2645 mlkem_results[k][0], 1.0 / mlkem_results[k][0],
2646 mlkem_results[k][1], 1.0 / mlkem_results[k][1]);
2647 }
2648
2472 mret = 0; 2649 mret = 0;
2473 2650
2474 end: 2651 end: