]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Provider-based KEM and SIG alg speed testing added
authorMichael Baentsch <57787676+baentsch@users.noreply.github.com>
Sat, 24 Dec 2022 08:20:44 +0000 (09:20 +0100)
committerTodd Short <todd.short@me.com>
Fri, 31 Mar 2023 18:19:18 +0000 (14:19 -0400)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Todd Short <todd.short@me.com>
(Merged from https://github.com/openssl/openssl/pull/19968)

apps/speed.c
doc/man1/openssl-speed.pod.in

index 489548f5ca7668a4023080cc29aae98741ae3963..025c4eedc4f10fb890bf949eb7940b1fd89f3042 100644 (file)
@@ -19,6 +19,8 @@
 #define EdDSA_SECONDS   PKEY_SECONDS
 #define SM2_SECONDS     PKEY_SECONDS
 #define FFDH_SECONDS    PKEY_SECONDS
+#define KEM_SECONDS     PKEY_SECONDS
+#define SIG_SECONDS     PKEY_SECONDS
 
 /* We need to use some deprecated APIs */
 #define OPENSSL_SUPPRESS_DEPRECATED
@@ -38,6 +40,7 @@
 #include <openssl/objects.h>
 #include <openssl/core_names.h>
 #include <openssl/async.h>
+#include <openssl/provider.h>
 #if !defined(OPENSSL_SYS_MSDOS)
 # include <unistd.h>
 #endif
@@ -111,6 +114,8 @@ typedef struct openssl_speed_sec_st {
     int eddsa;
     int sm2;
     int ffdh;
+    int kem;
+    int sig;
 } openssl_speed_sec_t;
 
 static volatile int run = 0;
@@ -122,6 +127,8 @@ static double Time_F(int s);
 static void print_message(const char *s, long num, int length, int tm);
 static void pkey_print_message(const char *str, const char *str2,
                                long num, unsigned int bits, int sec);
+static void kskey_print_message(const char *str, const char *str2, long num,
+                                 int tm);
 static void print_result(int alg, int run_no, int count, double time_used);
 #ifndef NO_FORK
 static int do_multi(int multi, int size_num);
@@ -230,7 +237,7 @@ typedef enum OPTION_choice {
     OPT_COMMON,
     OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
     OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM, OPT_PROV_ENUM, OPT_CONFIG,
-    OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC, OPT_MLOCK
+    OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC, OPT_MLOCK, OPT_KEM, OPT_SIG
 } OPTION_CHOICE;
 
 const OPTIONS speed_options[] = {
@@ -267,6 +274,10 @@ const OPTIONS speed_options[] = {
      "Time decryption instead of encryption (only EVP)"},
     {"aead", OPT_AEAD, '-',
      "Benchmark EVP-named AEAD cipher in TLS-like sequence"},
+    {"kem-algorithms", OPT_KEM, '-',
+     "Benchmark KEM algorithms"},
+    {"signature-algorithms", OPT_SIG, '-',
+     "Benchmark signature algorithms"},
 
     OPT_SECTION("Timing"),
     {"elapsed", OPT_ELAPSED, '-',
@@ -476,6 +487,16 @@ static const OPT_PAIR sm2_choices[SM2_NUM] = {
 static double sm2_results[SM2_NUM][2];    /* 2 ops: sign then verify */
 #endif /* OPENSSL_NO_SM2 */
 
+#define MAX_KEM_NUM 111
+static size_t kems_algs_len = 0;
+static char *kems_algname[MAX_KEM_NUM] = { NULL };
+static double kems_results[MAX_KEM_NUM][3];  /* keygen, encaps, decaps */
+
+#define MAX_SIG_NUM 111
+static size_t sigs_algs_len = 0;
+static char *sigs_algname[MAX_SIG_NUM] = { NULL };
+static double sigs_results[MAX_SIG_NUM][3];  /* keygen, sign, verify */
+
 #define COND(unused_cond) (run && count < INT_MAX)
 #define COUNT(d) (count)
 
@@ -513,6 +534,20 @@ typedef struct loopargs_st {
 #endif
     EVP_CIPHER_CTX *ctx;
     EVP_MAC_CTX *mctx;
+    EVP_PKEY_CTX *kem_gen_ctx[MAX_KEM_NUM];
+    EVP_PKEY_CTX *kem_encaps_ctx[MAX_KEM_NUM];
+    EVP_PKEY_CTX *kem_decaps_ctx[MAX_KEM_NUM];
+    size_t kem_out_len[MAX_KEM_NUM];
+    size_t kem_secret_len[MAX_KEM_NUM];
+    unsigned char *kem_out[MAX_KEM_NUM];
+    unsigned char *kem_send_secret[MAX_KEM_NUM];
+    unsigned char *kem_rcv_secret[MAX_KEM_NUM];
+    EVP_PKEY_CTX *sig_gen_ctx[MAX_KEM_NUM];
+    EVP_PKEY_CTX *sig_sign_ctx[MAX_KEM_NUM];
+    EVP_PKEY_CTX *sig_verify_ctx[MAX_KEM_NUM];
+    size_t sig_max_sig_len[MAX_KEM_NUM];
+    size_t sig_act_sig_len[MAX_KEM_NUM];
+    unsigned char *sig_sig[MAX_KEM_NUM];
 } loopargs_t;
 static int run_benchmark(int async_jobs, int (*loop_function) (void *),
                          loopargs_t * loopargs);
@@ -1139,6 +1174,131 @@ static int SM2_verify_loop(void *args)
 }
 #endif                         /* OPENSSL_NO_SM2 */
 
+static long kems_c[MAX_KEM_NUM][3]; /* keygen, encaps, decaps */
+static int KEM_keygen_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    EVP_PKEY_CTX *ctx = tempargs->kem_gen_ctx[testnum];
+    EVP_PKEY *pkey = NULL;
+    int count;
+
+    for (count = 0; COND(kems_c[testnum][0]); count++) {
+        if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
+            return -1;
+        /*
+         * runtime defined to quite some degree by randomness,
+         * so performance overhead of _free doesn't impact
+         * results significantly. In any case this test is
+         * meant to permit relative algorithm performance
+         * comparison.
+         */
+        EVP_PKEY_free(pkey);
+        pkey = NULL;
+    }
+    return count;
+}
+
+static int KEM_encaps_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    EVP_PKEY_CTX *ctx = tempargs->kem_encaps_ctx[testnum];
+    size_t out_len = tempargs->kem_out_len[testnum];
+    size_t secret_len = tempargs->kem_secret_len[testnum];
+    unsigned char *out = tempargs->kem_out[testnum];
+    unsigned char *secret = tempargs->kem_send_secret[testnum];
+    int count;
+
+    for (count = 0; COND(kems_c[testnum][1]); count++) {
+        if (EVP_PKEY_encapsulate(ctx, out, &out_len, secret, &secret_len) <= 0)
+            return -1;
+    }
+    return count;
+}
+
+static int KEM_decaps_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    EVP_PKEY_CTX *ctx = tempargs->kem_decaps_ctx[testnum];
+    size_t out_len = tempargs->kem_out_len[testnum];
+    size_t secret_len = tempargs->kem_secret_len[testnum];
+    unsigned char *out = tempargs->kem_out[testnum];
+    unsigned char *secret = tempargs->kem_send_secret[testnum];
+    int count;
+
+    for (count = 0; COND(kems_c[testnum][2]); count++) {
+        if (EVP_PKEY_decapsulate(ctx, secret, &secret_len, out, out_len) <= 0)
+            return -1;
+    }
+    return count;
+}
+
+static long sigs_c[MAX_SIG_NUM][3]; /* keygen, sign, verify */
+static int SIG_keygen_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    EVP_PKEY_CTX *ctx = tempargs->sig_gen_ctx[testnum];
+    EVP_PKEY *pkey = NULL;
+    int count;
+
+    for (count = 0; COND(kems_c[testnum][0]); count++) {
+        EVP_PKEY_keygen(ctx, &pkey);
+        /* TBD: How much does free influence runtime? */
+        EVP_PKEY_free(pkey);
+        pkey = NULL;
+    }
+    return count;
+}
+
+static int SIG_sign_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    EVP_PKEY_CTX *ctx = tempargs->sig_sign_ctx[testnum];
+    /* be sure to not change stored sig: */
+    unsigned char *sig = app_malloc(tempargs->sig_max_sig_len[testnum],
+                                    "sig sign loop");
+    unsigned char md[SHA256_DIGEST_LENGTH] = { 0 };
+    size_t md_len = SHA256_DIGEST_LENGTH;
+    int count;
+
+    for (count = 0; COND(kems_c[testnum][1]); count++) {
+        size_t sig_len = tempargs->sig_max_sig_len[testnum];
+        int ret = EVP_PKEY_sign(ctx, sig, &sig_len, md, md_len);
+
+        if (ret <= 0) {
+            BIO_printf(bio_err, "SIG sign failure at count %d\n", count);
+            ERR_print_errors(bio_err);
+            count = -1;
+            break;
+        }
+    }
+    OPENSSL_free(sig);
+    return count;
+}
+
+static int SIG_verify_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    EVP_PKEY_CTX *ctx = tempargs->sig_verify_ctx[testnum];
+    size_t sig_len = tempargs->sig_act_sig_len[testnum];
+    unsigned char *sig = tempargs->sig_sig[testnum];
+    unsigned char md[SHA256_DIGEST_LENGTH] = { 0 };
+    size_t md_len = SHA256_DIGEST_LENGTH;
+    int count;
+
+    for (count = 0; COND(kems_c[testnum][2]); count++) {
+        int ret = EVP_PKEY_verify(ctx, sig, sig_len, md, md_len);
+
+        if (ret <= 0) {
+            BIO_printf(bio_err, "SIG verify failure at count %d\n", count);
+            ERR_print_errors(bio_err);
+            count = -1;
+            break;
+        }
+
+    }
+    return count;
+}
+
 static int run_benchmark(int async_jobs,
                          int (*loop_function) (void *), loopargs_t * loopargs)
 {
@@ -1373,6 +1533,99 @@ static EVP_PKEY *get_ecdsa(const EC_CURVE *curve)
 #define stop_it(do_it, test_num)\
     memset(do_it + test_num, 0, OSSL_NELEM(do_it) - test_num);
 
+/* Checks to see if algorithms are fetchable */
+#define IS_FETCHABLE(type, TYPE)                                \
+    static int is_ ## type ## _fetchable(const TYPE *alg)       \
+    {                                                           \
+        TYPE *impl;                                             \
+        const char *propq = app_get0_propq();                   \
+        OSSL_LIB_CTX *libctx = app_get0_libctx();               \
+        const char *name = TYPE ## _get0_name(alg);             \
+                                                                \
+        ERR_set_mark();                                         \
+        impl = TYPE ## _fetch(libctx, name, propq);             \
+        ERR_pop_to_mark();                                      \
+        if (impl == NULL)                                       \
+            return 0;                                           \
+        TYPE ## _free(impl);                                    \
+        return 1;                                               \
+    }
+
+IS_FETCHABLE(signature, EVP_SIGNATURE)
+IS_FETCHABLE(kem, EVP_KEM)
+
+DEFINE_STACK_OF(EVP_KEM)
+
+static int kems_cmp(const EVP_KEM * const *a,
+                    const EVP_KEM * const *b)
+{
+    return strcmp(OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*a)),
+                  OSSL_PROVIDER_get0_name(EVP_KEM_get0_provider(*b)));
+}
+
+static void collect_kem(EVP_KEM *kem, void *stack)
+{
+    STACK_OF(EVP_KEM) *kem_stack = stack;
+
+    if (is_kem_fetchable(kem)
+            && sk_EVP_KEM_push(kem_stack, kem) > 0) {
+        EVP_KEM_up_ref(kem);
+    }
+}
+
+static int kem_locate(const char *algo, unsigned int *idx)
+{
+    unsigned int i;
+
+    for (i = 0; i < kems_algs_len; i++) {
+        if (strcmp(kems_algname[i], algo) == 0) {
+            *idx = i;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+DEFINE_STACK_OF(EVP_SIGNATURE)
+
+static int signatures_cmp(const EVP_SIGNATURE * const *a,
+                          const EVP_SIGNATURE * const *b)
+{
+    return strcmp(OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*a)),
+                  OSSL_PROVIDER_get0_name(EVP_SIGNATURE_get0_provider(*b)));
+}
+
+static void collect_signatures(EVP_SIGNATURE *sig, void *stack)
+{
+    STACK_OF(EVP_SIGNATURE) *sig_stack = stack;
+
+    if (is_signature_fetchable(sig)
+            && sk_EVP_SIGNATURE_push(sig_stack, sig) > 0)
+        EVP_SIGNATURE_up_ref(sig);
+}
+
+static int sig_locate(const char *algo, unsigned int *idx)
+{
+    unsigned int i;
+
+    for (i = 0; i < sigs_algs_len; i++) {
+        if (strcmp(sigs_algname[i], algo) == 0) {
+            *idx = i;
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static int get_max(const uint8_t doit[], size_t algs_len) {
+    size_t i = 0;
+    int maxcnt = 0;
+
+    for (i = 0; i < algs_len; i++)
+        if (maxcnt < doit[i]) maxcnt = doit[i];
+    return maxcnt;
+}
+
 int speed_main(int argc, char **argv)
 {
     CONF *conf = NULL;
@@ -1387,9 +1640,12 @@ int speed_main(int argc, char **argv)
     int async_init = 0, multiblock = 0, pr_header = 0;
     uint8_t doit[ALGOR_NUM] = { 0 };
     int ret = 1, misalign = 0, lengths_single = 0, aead = 0;
+    STACK_OF(EVP_KEM) *kem_stack = NULL;
+    STACK_OF(EVP_SIGNATURE) *sig_stack = NULL;
     long count = 0;
     unsigned int size_num = SIZE_NUM;
     unsigned int i, k, loopargs_len = 0, async_jobs = 0;
+    unsigned int idx;
     int keylen;
     int buflen;
     BIGNUM *bn = NULL;
@@ -1401,7 +1657,8 @@ int speed_main(int argc, char **argv)
     openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
                                     ECDSA_SECONDS, ECDH_SECONDS,
                                     EdDSA_SECONDS, SM2_SECONDS,
-                                    FFDH_SECONDS };
+                                    FFDH_SECONDS, KEM_SECONDS,
+                                    SIG_SECONDS };
 
     static const unsigned char key32[32] = {
         0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
@@ -1501,6 +1758,12 @@ int speed_main(int argc, char **argv)
     uint8_t ecdh_doit[EC_NUM] = { 0 };
     uint8_t eddsa_doit[EdDSA_NUM] = { 0 };
 
+    uint8_t kems_doit[MAX_KEM_NUM] = { 0 };
+    uint8_t sigs_doit[MAX_SIG_NUM] = { 0 };
+
+    uint8_t do_kems = 0;
+    uint8_t do_sigs = 0;
+
     /* checks declared curves against choices list. */
     OPENSSL_assert(ed_curves[EdDSA_NUM - 1].nid == NID_ED448);
     OPENSSL_assert(strcmp(eddsa_choices[EdDSA_NUM - 1].name, "ed448") == 0);
@@ -1643,7 +1906,8 @@ int speed_main(int argc, char **argv)
         case OPT_SECONDS:
             seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
                         = seconds.ecdh = seconds.eddsa
-                        = seconds.sm2 = seconds.ffdh = opt_int_arg();
+                        = seconds.sm2 = seconds.ffdh
+                        = seconds.kem = seconds.sig = opt_int_arg();
             break;
         case OPT_BYTES:
             lengths_single = opt_int_arg();
@@ -1653,6 +1917,12 @@ int speed_main(int argc, char **argv)
         case OPT_AEAD:
             aead = 1;
             break;
+        case OPT_KEM:
+            do_kems = 1;
+            break;
+        case OPT_SIG:
+            do_sigs = 1;
+            break;
         case OPT_MLOCK:
             domlock = 1;
 #if !defined(_WIN32) && !defined(OPENSSL_SYS_LINUX)
@@ -1665,6 +1935,102 @@ int speed_main(int argc, char **argv)
         }
     }
 
+    /* find all KEMs currently available */
+    kem_stack = sk_EVP_KEM_new(kems_cmp);
+    EVP_KEM_do_all_provided(app_get0_libctx(), collect_kem, kem_stack);
+
+    kems_algs_len = 0;
+
+    for (idx = 0; idx < (unsigned int)sk_EVP_KEM_num(kem_stack); idx++) {
+        EVP_KEM *kem = sk_EVP_KEM_value(kem_stack, idx);
+
+        if (strcmp(EVP_KEM_get0_name(kem), "RSA") == 0) {
+            if (kems_algs_len + OSSL_NELEM(rsa_choices) >= MAX_KEM_NUM) {
+                BIO_printf(bio_err,
+                           "Too many KEMs registered. Change MAX_KEM_NUM.\n");
+                goto end;
+            }
+            for (i = 0; i < OSSL_NELEM(rsa_choices); i++) {
+                kems_doit[kems_algs_len] = 1;
+                kems_algname[kems_algs_len++] = OPENSSL_strdup(rsa_choices[i].name);
+            }
+        } else if (strcmp(EVP_KEM_get0_name(kem), "EC") == 0) {
+            if (kems_algs_len + 3 >= MAX_KEM_NUM) {
+                BIO_printf(bio_err,
+                           "Too many KEMs registered. Change MAX_KEM_NUM.\n");
+                goto end;
+            }
+            kems_doit[kems_algs_len] = 1;
+            kems_algname[kems_algs_len++] = OPENSSL_strdup("ECP-256");
+            kems_doit[kems_algs_len] = 1;
+            kems_algname[kems_algs_len++] = OPENSSL_strdup("ECP-384");
+            kems_doit[kems_algs_len] = 1;
+            kems_algname[kems_algs_len++] = OPENSSL_strdup("ECP-521");
+        } else {
+            if (kems_algs_len + 1 >= MAX_KEM_NUM) {
+                BIO_printf(bio_err,
+                           "Too many KEMs registered. Change MAX_KEM_NUM.\n");
+                goto end;
+            }
+            kems_doit[kems_algs_len] = 1;
+            kems_algname[kems_algs_len++] = OPENSSL_strdup(EVP_KEM_get0_name(kem));
+        }
+    }
+    sk_EVP_KEM_pop_free(kem_stack, EVP_KEM_free);
+    kem_stack = NULL;
+
+    /* find all SIGNATUREs currently available */
+    sig_stack = sk_EVP_SIGNATURE_new(signatures_cmp);
+    EVP_SIGNATURE_do_all_provided(app_get0_libctx(), collect_signatures, sig_stack);
+
+    sigs_algs_len = 0;
+
+    for (idx = 0; idx < (unsigned int)sk_EVP_SIGNATURE_num(sig_stack); idx++) {
+        EVP_SIGNATURE *s = sk_EVP_SIGNATURE_value(sig_stack, idx);
+        const char *sig_name = EVP_SIGNATURE_get0_name(s);
+
+        if (strcmp(sig_name, "RSA") == 0) {
+            if (sigs_algs_len + OSSL_NELEM(rsa_choices) >= MAX_SIG_NUM) {
+                BIO_printf(bio_err,
+                           "Too many signatures registered. Change MAX_SIG_NUM.\n");
+                goto end;
+            }
+            for (i = 0; i < OSSL_NELEM(rsa_choices); i++) {
+                sigs_doit[sigs_algs_len] = 1;
+                sigs_algname[sigs_algs_len++] = OPENSSL_strdup(rsa_choices[i].name);
+            }
+        }
+        else if (strcmp(sig_name, "DSA") == 0) {
+            if (sigs_algs_len + DSA_NUM >= MAX_SIG_NUM) {
+                BIO_printf(bio_err,
+                           "Too many signatures registered. Change MAX_SIG_NUM.\n");
+                goto end;
+            }
+            for (i = 0; i < DSA_NUM; i++) {
+                sigs_doit[sigs_algs_len] = 1;
+                sigs_algname[sigs_algs_len++] = OPENSSL_strdup(dsa_choices[i].name);
+            }
+        }
+        /* skipping these algs as tested elsewhere - and b/o setup is a pain */
+        else if (strcmp(sig_name, "ED25519") &&
+                 strcmp(sig_name, "ED448") &&
+                 strcmp(sig_name, "ECDSA") &&
+                 strcmp(sig_name, "HMAC") &&
+                 strcmp(sig_name, "SIPHASH") &&
+                 strcmp(sig_name, "POLY1305") &&
+                 strcmp(sig_name, "CMAC") &&
+                 strcmp(sig_name, "SM2")) { /* skip alg */
+            if (sigs_algs_len + 1 >= MAX_SIG_NUM) {
+                BIO_printf(bio_err,
+                           "Too many signatures registered. Change MAX_SIG_NUM.\n");
+                goto end;
+            }
+            /* activate this provider algorithm */
+            sigs_doit[sigs_algs_len] = 1;
+            sigs_algname[sigs_algs_len++] = OPENSSL_strdup(sig_name);
+        }
+    }
+
     /* Remaining arguments are algorithms. */
     argc = opt_num_rest();
     argv = opt_rest();
@@ -1674,103 +2040,117 @@ int speed_main(int argc, char **argv)
 
     for (; *argv; argv++) {
         const char *algo = *argv;
+        int algo_found = 0;
 
         if (opt_found(algo, doit_choices, &i)) {
             doit[i] = 1;
-            continue;
+            algo_found = 1;
         }
         if (strcmp(algo, "des") == 0) {
             doit[D_CBC_DES] = doit[D_EDE3_DES] = 1;
-            continue;
+            algo_found = 1;
         }
         if (strcmp(algo, "sha") == 0) {
             doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1;
-            continue;
+            algo_found = 1;
         }
 #ifndef OPENSSL_NO_DEPRECATED_3_0
         if (strcmp(algo, "openssl") == 0) /* just for compatibility */
-            continue;
+            algo_found = 1;
 #endif
         if (HAS_PREFIX(algo, "rsa")) {
             if (algo[sizeof("rsa") - 1] == '\0') {
                 memset(rsa_doit, 1, sizeof(rsa_doit));
-                continue;
+                algo_found = 1;
             }
             if (opt_found(algo, rsa_choices, &i)) {
                 rsa_doit[i] = 1;
-                continue;
+                algo_found = 1;
             }
         }
 #ifndef OPENSSL_NO_DH
         if (HAS_PREFIX(algo, "ffdh")) {
             if (algo[sizeof("ffdh") - 1] == '\0') {
                 memset(ffdh_doit, 1, sizeof(ffdh_doit));
-                continue;
+                algo_found = 1;
             }
             if (opt_found(algo, ffdh_choices, &i)) {
                 ffdh_doit[i] = 2;
-                continue;
+                algo_found = 1;
             }
         }
 #endif
         if (HAS_PREFIX(algo, "dsa")) {
             if (algo[sizeof("dsa") - 1] == '\0') {
                 memset(dsa_doit, 1, sizeof(dsa_doit));
-                continue;
+                algo_found = 1;
             }
             if (opt_found(algo, dsa_choices, &i)) {
                 dsa_doit[i] = 2;
-                continue;
+                algo_found = 1;
             }
         }
         if (strcmp(algo, "aes") == 0) {
             doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1;
-            continue;
+            algo_found = 1;
         }
         if (strcmp(algo, "camellia") == 0) {
             doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1;
-            continue;
+            algo_found = 1;
         }
         if (HAS_PREFIX(algo, "ecdsa")) {
             if (algo[sizeof("ecdsa") - 1] == '\0') {
                 memset(ecdsa_doit, 1, sizeof(ecdsa_doit));
-                continue;
+                algo_found = 1;
             }
             if (opt_found(algo, ecdsa_choices, &i)) {
                 ecdsa_doit[i] = 2;
-                continue;
+                algo_found = 1;
             }
         }
         if (HAS_PREFIX(algo, "ecdh")) {
             if (algo[sizeof("ecdh") - 1] == '\0') {
                 memset(ecdh_doit, 1, sizeof(ecdh_doit));
-                continue;
+                algo_found = 1;
             }
             if (opt_found(algo, ecdh_choices, &i)) {
                 ecdh_doit[i] = 2;
-                continue;
+                algo_found = 1;
             }
         }
         if (strcmp(algo, "eddsa") == 0) {
             memset(eddsa_doit, 1, sizeof(eddsa_doit));
-            continue;
+            algo_found = 1;
         }
         if (opt_found(algo, eddsa_choices, &i)) {
             eddsa_doit[i] = 2;
-            continue;
+            algo_found = 1;
         }
 #ifndef OPENSSL_NO_SM2
         if (strcmp(algo, "sm2") == 0) {
             memset(sm2_doit, 1, sizeof(sm2_doit));
-            continue;
+            algo_found = 1;
         }
         if (opt_found(algo, sm2_choices, &i)) {
             sm2_doit[i] = 2;
-            continue;
+            algo_found = 1;
         }
 #endif
-        BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo);
-        goto end;
+        if (kem_locate(algo, &idx)) {
+            kems_doit[idx]++;
+            do_kems = 1;
+            algo_found = 1;
+        }
+        if (sig_locate(algo, &idx)) {
+            sigs_doit[idx]++;
+            do_sigs = 1;
+            algo_found = 1;
+        }
+
+        if (!algo_found) {
+            BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, algo);
+            goto end;
+        }
     }
 
     /* Sanity checks */
@@ -1785,6 +2165,28 @@ int speed_main(int argc, char **argv)
             goto end;
         }
     }
+    if (kems_algs_len > 0) {
+        int maxcnt = get_max(kems_doit, kems_algs_len);
+
+        if (maxcnt > 1) {
+            /* some algs explicitly selected */
+            for (i = 0; i < kems_algs_len; i++) {
+                /* disable the rest */
+                kems_doit[i]--;
+            }
+        }
+    }
+    if (sigs_algs_len > 0) {
+        int maxcnt = get_max(sigs_doit, sigs_algs_len);
+
+        if (maxcnt > 1) {
+            /* some algs explicitly selected */
+            for (i = 0; i < sigs_algs_len; i++) {
+                /* disable the rest */
+                sigs_doit[i]--;
+            }
+        }
+    }
     if (multiblock) {
         if (evp_cipher == NULL) {
             BIO_printf(bio_err, "-mb can be used only with a multi-block"
@@ -1871,7 +2273,8 @@ int speed_main(int argc, char **argv)
     e = setup_engine(engine_id, 0);
 
     /* No parameters; turn on everything. */
-    if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC] && !doit[D_EVP_CMAC]) {
+    if (argc == 0 && !doit[D_EVP] && !doit[D_HMAC]
+        && !doit[D_EVP_CMAC] && !do_kems && !do_sigs) {
         memset(doit, 1, sizeof(doit));
         doit[D_EVP] = doit[D_EVP_CMAC] = 0;
         ERR_set_mark();
@@ -1909,6 +2312,10 @@ int speed_main(int argc, char **argv)
 #ifndef OPENSSL_NO_SM2
         memset(sm2_doit, 1, sizeof(sm2_doit));
 #endif
+        memset(kems_doit, 1, sizeof(kems_doit));
+        do_kems = 1;
+        memset(sigs_doit, 1, sizeof(sigs_doit));
+        do_sigs = 1;
     }
     for (i = 0; i < ALGOR_NUM; i++)
         if (doit[i])
@@ -3170,6 +3577,371 @@ skip_hmac:
         }
     }
 #endif  /* OPENSSL_NO_DH */
+
+    for (testnum = 0; testnum < kems_algs_len; testnum++) {
+        int kem_checks = 1;
+        const char *kem_name = kems_algname[testnum];
+
+        if (!kems_doit[testnum] || !do_kems)
+            continue;
+
+        for (i = 0; i < loopargs_len; i++) {
+            EVP_PKEY *pkey = NULL;
+            EVP_PKEY_CTX *kem_gen_ctx = NULL;
+            EVP_PKEY_CTX *kem_encaps_ctx = NULL;
+            EVP_PKEY_CTX *kem_decaps_ctx = NULL;
+            size_t send_secret_len, out_len;
+            size_t rcv_secret_len;
+            unsigned char *out = NULL, *send_secret = NULL, *rcv_secret;
+            size_t bits;
+            char *name;
+            OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+            int use_params = 0;
+            enum kem_type_t { KEM_RSA = 1, KEM_EC, KEM_X25519, KEM_X448 } kem_type;
+
+            if (strncmp(kem_name, "rsa", 3) == 0)
+                kem_type = KEM_RSA;
+            else if (strncmp(kem_name, "EC", 2) == 0)
+                kem_type = KEM_EC;
+            else if (strcmp(kem_name, "X25519") == 0)
+                kem_type = KEM_X25519;
+            else if (strcmp(kem_name, "X448") == 0)
+                kem_type = KEM_X448;
+            else kem_type = 0;
+
+            if (ERR_peek_error()) {
+                BIO_printf(bio_err,
+                           "WARNING: the error queue contains previous unhandled errors.\n");
+                ERR_print_errors(bio_err);
+            }
+
+            if (kem_type == KEM_RSA) {
+                bits = atoi(kem_name + 3);
+                params[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS,
+                                                        &bits);
+                use_params = 1;
+            } else if (kem_type == KEM_EC) {
+                name = (char *)(kem_name + 2);
+                params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
+                                                  name, 0);
+                use_params = 1;
+            }
+
+            kem_gen_ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(),
+                                               (kem_type == KEM_RSA) ? "RSA":
+                                                (kem_type == KEM_EC) ? "EC":
+                                                 kem_name,
+                                               app_get0_propq());
+
+            if ((!kem_gen_ctx || EVP_PKEY_keygen_init(kem_gen_ctx) <= 0)
+                || (use_params
+                    && EVP_PKEY_CTX_set_params(kem_gen_ctx, params) <= 0)) {
+                BIO_printf(bio_err, "Error initializing keygen ctx for %s.\n",
+                           kem_name);
+                goto kem_err_break;
+            }
+            if (EVP_PKEY_keygen(kem_gen_ctx, &pkey) <= 0) {
+                BIO_printf(bio_err, "Error while generating KEM EVP_PKEY.\n");
+                goto kem_err_break;
+            }
+            /* Now prepare encaps data structs */
+            kem_encaps_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
+                                                        pkey,
+                                                        app_get0_propq());
+            if (kem_encaps_ctx == NULL
+                || EVP_PKEY_encapsulate_init(kem_encaps_ctx, NULL) <= 0
+                || (kem_type == KEM_RSA
+                    && EVP_PKEY_CTX_set_kem_op(kem_encaps_ctx, "RSASVE") <= 0)
+                || ((kem_type == KEM_EC
+                    || kem_type == KEM_X25519
+                    || kem_type == KEM_X448)
+                   && EVP_PKEY_CTX_set_kem_op(kem_encaps_ctx, "DHKEM") <= 0)
+                || EVP_PKEY_encapsulate(kem_encaps_ctx, NULL, &out_len,
+                                      NULL, &send_secret_len) <= 0) {
+                BIO_printf(bio_err,
+                           "Error while initializing encaps data structs for %s.\n",
+                           kem_name);
+                goto kem_err_break;
+            }
+            out = app_malloc(out_len, "encaps result");
+            send_secret = app_malloc(send_secret_len, "encaps secret");
+            if (out == NULL || send_secret == NULL) {
+                BIO_printf(bio_err, "MemAlloc error in encaps for %s.\n", kem_name);
+                goto kem_err_break;
+            }
+            if (EVP_PKEY_encapsulate(kem_encaps_ctx, out, &out_len,
+                                     send_secret, &send_secret_len) <= 0) {
+                BIO_printf(bio_err, "Encaps error for %s.\n", kem_name);
+                goto kem_err_break;
+            }
+            /* Now prepare decaps data structs */
+            kem_decaps_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
+                                                        pkey,
+                                                        app_get0_propq());
+            if (kem_decaps_ctx == NULL
+                || EVP_PKEY_decapsulate_init(kem_decaps_ctx, NULL) <= 0
+                || (kem_type == KEM_RSA
+                  && EVP_PKEY_CTX_set_kem_op(kem_decaps_ctx, "RSASVE") <= 0)
+                || ((kem_type == KEM_EC
+                     || kem_type == KEM_X25519
+                     || kem_type == KEM_X448)
+                  && EVP_PKEY_CTX_set_kem_op(kem_decaps_ctx, "DHKEM") <= 0)
+                || EVP_PKEY_decapsulate(kem_decaps_ctx, NULL, &rcv_secret_len,
+                                        out, out_len) <= 0) {
+                BIO_printf(bio_err,
+                           "Error while initializing decaps data structs for %s.\n",
+                           kem_name);
+                goto kem_err_break;
+            }
+            rcv_secret = app_malloc(rcv_secret_len, "KEM decaps secret");
+            if (rcv_secret == NULL) {
+                BIO_printf(bio_err, "MemAlloc failure in decaps for %s.\n",
+                           kem_name);
+                goto kem_err_break;
+            }
+            if (EVP_PKEY_decapsulate(kem_decaps_ctx, rcv_secret,
+                                     &rcv_secret_len, out, out_len) <= 0
+                || rcv_secret_len != send_secret_len
+                || memcmp(send_secret, rcv_secret, send_secret_len)) {
+                BIO_printf(bio_err, "Decaps error for %s.\n", kem_name);
+                goto kem_err_break;
+            }
+            loopargs[i].kem_gen_ctx[testnum] = kem_gen_ctx;
+            loopargs[i].kem_encaps_ctx[testnum] = kem_encaps_ctx;
+            loopargs[i].kem_decaps_ctx[testnum] = kem_decaps_ctx;
+            loopargs[i].kem_out_len[testnum] = out_len;
+            loopargs[i].kem_secret_len[testnum] = send_secret_len;
+            loopargs[i].kem_out[testnum] = out;
+            loopargs[i].kem_send_secret[testnum] = send_secret;
+            loopargs[i].kem_rcv_secret[testnum] = rcv_secret;
+            break;
+
+        kem_err_break:
+            ERR_print_errors(bio_err);
+            op_count = 1;
+            kem_checks = 0;
+            break;
+        }
+        if (kem_checks != 0) {
+            kskey_print_message(kem_name, "keygen", kems_c[testnum][0],
+                                seconds.kem);
+            Time_F(START);
+            count =
+                run_benchmark(async_jobs, KEM_keygen_loop, loopargs);
+            d = Time_F(STOP);
+            BIO_printf(bio_err,
+                       mr ? "+R13:%ld:%s:%.2f\n" :
+                       "%ld %s KEM keygens in %.2fs\n", count,
+                       kem_name, d);
+            kems_results[testnum][0] = (double)count / d;
+            op_count = count;
+            kskey_print_message(kem_name, "encaps", kems_c[testnum][1],
+                                seconds.kem);
+            Time_F(START);
+            count =
+                run_benchmark(async_jobs, KEM_encaps_loop, loopargs);
+            d = Time_F(STOP);
+            BIO_printf(bio_err,
+                       mr ? "+R14:%ld:%s:%.2f\n" :
+                       "%ld %s KEM encaps in %.2fs\n", count,
+                       kem_name, d);
+            kems_results[testnum][1] = (double)count / d;
+            op_count = count;
+            kskey_print_message(kem_name, "decaps", kems_c[testnum][2],
+                                seconds.kem);
+            Time_F(START);
+            count =
+                run_benchmark(async_jobs, KEM_decaps_loop, loopargs);
+            d = Time_F(STOP);
+            BIO_printf(bio_err,
+                       mr ? "+R15:%ld:%s:%.2f\n" :
+                       "%ld %s KEM decaps in %.2fs\n", count,
+                       kem_name, d);
+            kems_results[testnum][2] = (double)count / d;
+            op_count = count;
+        }
+        if (op_count <= 1) {
+            /* if longer than 10s, don't do any more */
+            stop_it(kems_doit, testnum);
+        }
+    }
+
+    for (testnum = 0; testnum < sigs_algs_len; testnum++) {
+        int sig_checks = 1;
+        const char *sig_name = sigs_algname[testnum];
+
+        if (!sigs_doit[testnum] || !do_sigs)
+            continue;
+
+        for (i = 0; i < loopargs_len; i++) {
+            EVP_PKEY *pkey = NULL;
+            EVP_PKEY_CTX *ctx_params = NULL;
+            EVP_PKEY* pkey_params = NULL;
+            EVP_PKEY_CTX *sig_gen_ctx = NULL;
+            EVP_PKEY_CTX *sig_sign_ctx = NULL;
+            EVP_PKEY_CTX *sig_verify_ctx = NULL;
+            unsigned char md[SHA256_DIGEST_LENGTH];
+            unsigned char *sig;
+            size_t md_len = SHA256_DIGEST_LENGTH;
+            size_t max_sig_len, sig_len;
+            size_t bits;
+            OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
+            int use_params = 0;
+
+            /* only sign little data to avoid measuring digest performance */
+            memset(md, 0, SHA256_DIGEST_LENGTH);
+
+            if (ERR_peek_error()) {
+                BIO_printf(bio_err,
+                           "WARNING: the error queue contains previous unhandled errors.\n");
+                ERR_print_errors(bio_err);
+            }
+
+            if (strncmp(sig_name, "rsa", 3) == 0) {
+                bits = atoi(sig_name + 3);
+                params[0] = OSSL_PARAM_construct_size_t(OSSL_PKEY_PARAM_RSA_BITS,
+                                                        &bits);
+                use_params = 1;
+            }
+
+            if (strncmp(sig_name, "dsa", 3) == 0) {
+                ctx_params = EVP_PKEY_CTX_new_id(EVP_PKEY_DSA, NULL);
+                if (ctx_params == NULL
+                    || EVP_PKEY_paramgen_init(ctx_params) <= 0
+                    || EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx_params,
+                                                        atoi(sig_name + 3)) <= 0
+                    || EVP_PKEY_paramgen(ctx_params, &pkey_params) <= 0
+                    || (sig_gen_ctx = EVP_PKEY_CTX_new(pkey_params, NULL)) == NULL
+                    || EVP_PKEY_keygen_init(sig_gen_ctx) <= 0) {
+                    BIO_printf(bio_err,
+                               "Error initializing classic keygen ctx for %s.\n",
+                               sig_name);
+                    goto sig_err_break;
+                }
+            }
+
+            if (sig_gen_ctx == NULL)
+                sig_gen_ctx = EVP_PKEY_CTX_new_from_name(app_get0_libctx(),
+                                      (strncmp(sig_name, "rsa", 3) == 0) ? "RSA" : sig_name,
+                                      app_get0_propq());
+
+            if (!sig_gen_ctx || EVP_PKEY_keygen_init(sig_gen_ctx) <= 0
+                || (use_params &&
+                    EVP_PKEY_CTX_set_params(sig_gen_ctx, params) <= 0)) {
+                BIO_printf(bio_err, "Error initializing keygen ctx for %s.\n",
+                           sig_name);
+                goto sig_err_break;
+            }
+            if (EVP_PKEY_keygen(sig_gen_ctx, &pkey) <= 0) {
+                BIO_printf(bio_err,
+                           "Error while generating signature EVP_PKEY for %s.\n",
+                           sig_name);
+                goto sig_err_break;
+            }
+            /* Now prepare signature data structs */
+            sig_sign_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
+                                                      pkey,
+                                                      app_get0_propq());
+            if (sig_sign_ctx == NULL
+                || EVP_PKEY_sign_init(sig_sign_ctx) <= 0
+                || (strncmp(sig_name, "rsa", 3) == 0
+                    && (EVP_PKEY_CTX_set_rsa_padding(sig_sign_ctx,
+                                                     RSA_PKCS1_PADDING) <= 0))
+                || EVP_PKEY_sign(sig_sign_ctx, NULL, &max_sig_len,
+                                 md, md_len) <= 0) {
+                    BIO_printf(bio_err,
+                               "Error while initializing signing data structs for %s.\n",
+                               sig_name);
+                    goto sig_err_break;
+            }
+            sig = app_malloc(sig_len = max_sig_len, "signature buffer");
+            if (sig == NULL) {
+                BIO_printf(bio_err, "MemAlloc error in sign for %s.\n", sig_name);
+                goto sig_err_break;
+            }
+            if (EVP_PKEY_sign(sig_sign_ctx, sig, &sig_len, md, md_len) <= 0) {
+                BIO_printf(bio_err, "Signing error for %s.\n", sig_name);
+                goto sig_err_break;
+            }
+            /* Now prepare verify data structs */
+            memset(md, 0, SHA256_DIGEST_LENGTH);
+            sig_verify_ctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(),
+                                                        pkey,
+                                                        app_get0_propq());
+            if (sig_verify_ctx == NULL
+                || EVP_PKEY_verify_init(sig_verify_ctx) <= 0
+                || (strncmp(sig_name, "rsa", 3) == 0
+                  && (EVP_PKEY_CTX_set_rsa_padding(sig_verify_ctx,
+                                                   RSA_PKCS1_PADDING) <= 0))) {
+                BIO_printf(bio_err,
+                           "Error while initializing verify data structs for %s.\n",
+                           sig_name);
+                goto sig_err_break;
+            }
+            if (EVP_PKEY_verify(sig_verify_ctx, sig, sig_len, md, md_len) <= 0) {
+                BIO_printf(bio_err, "Verify error for %s.\n", sig_name);
+                goto sig_err_break;
+            }
+            if (EVP_PKEY_verify(sig_verify_ctx, sig, sig_len, md, md_len) <= 0) {
+                BIO_printf(bio_err, "Verify 2 error for %s.\n", sig_name);
+                goto sig_err_break;
+            }
+            loopargs[i].sig_gen_ctx[testnum] = sig_gen_ctx;
+            loopargs[i].sig_sign_ctx[testnum] = sig_sign_ctx;
+            loopargs[i].sig_verify_ctx[testnum] = sig_verify_ctx;
+            loopargs[i].sig_max_sig_len[testnum] = max_sig_len;
+            loopargs[i].sig_act_sig_len[testnum] = sig_len;
+            loopargs[i].sig_sig[testnum] = sig;
+            break;
+
+        sig_err_break:
+            ERR_print_errors(bio_err);
+            op_count = 1;
+            sig_checks = 0;
+            break;
+        }
+
+        if (sig_checks != 0) {
+            kskey_print_message(sig_name, "keygen", sigs_c[testnum][0], seconds.sig);
+            Time_F(START);
+            count = run_benchmark(async_jobs, SIG_keygen_loop, loopargs);
+            d = Time_F(STOP);
+            BIO_printf(bio_err,
+                       mr ? "+R16:%ld:%s:%.2f\n" :
+                       "%ld %s signature keygens in %.2fs\n", count,
+                       sig_name, d);
+            sigs_results[testnum][0] = (double)count / d;
+            op_count = count;
+            kskey_print_message(sig_name, "signs", sigs_c[testnum][1],
+                                 seconds.sig);
+            Time_F(START);
+            count =
+                run_benchmark(async_jobs, SIG_sign_loop, loopargs);
+            d = Time_F(STOP);
+            BIO_printf(bio_err,
+                       mr ? "+R17:%ld:%s:%.2f\n" :
+                       "%ld %s signature signs in %.2fs\n", count,
+                       sig_name, d);
+            sigs_results[testnum][1] = (double)count / d;
+            op_count = count;
+
+            kskey_print_message(sig_name, "verify", sigs_c[testnum][2],
+                                 seconds.sig);
+            Time_F(START);
+            count =
+                run_benchmark(async_jobs, SIG_verify_loop, loopargs);
+            d = Time_F(STOP);
+            BIO_printf(bio_err,
+                       mr ? "+R18:%ld:%s:%.2f\n" :
+                       "%ld %s signature verifys in %.2fs\n", count,
+                       sig_name, d);
+            sigs_results[testnum][2] = (double)count / d;
+            op_count = count;
+        }
+        if (op_count <= 1)
+            stop_it(sigs_doit, testnum);
+    }
+
 #ifndef NO_FORK
  show_res:
 #endif
@@ -3221,7 +3993,8 @@ skip_hmac:
                    k, rsa_keys[k].bits, rsa_results[k][0], rsa_results[k][1]);
         else
             printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
-                   rsa_keys[k].bits, 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1],
+                   rsa_keys[k].bits, 1.0 / rsa_results[k][0],
+                   1.0 / rsa_results[k][1],
                    rsa_results[k][0], rsa_results[k][1]);
     }
     testnum = 1;
@@ -3341,6 +4114,48 @@ skip_hmac:
     }
 #endif /* OPENSSL_NO_DH */
 
+    testnum = 1;
+    for (k = 0; k < kems_algs_len; k++) {
+        const char *kem_name = kems_algname[k];
+
+        if (!kems_doit[k] || !do_kems)
+            continue;
+        if (testnum && !mr) {
+            printf("%31skeygen    encaps    decaps keygens/s  encaps/s  decaps/s\n", " ");
+            testnum = 0;
+        }
+        if (mr)
+            printf("+F9:%u:%f:%f:%f\n",
+                   k, kems_results[k][0], kems_results[k][1],
+                   kems_results[k][2]);
+        else
+            printf("%27s %8.6fs %8.6fs %8.6fs %9.1f %9.1f %9.1f\n", kem_name,
+                   1.0 / kems_results[k][0],
+                   1.0 / kems_results[k][1], 1.0 / kems_results[k][2],
+                   kems_results[k][0], kems_results[k][1], kems_results[k][2]);
+    }
+    ret = 0;
+
+    testnum = 1;
+    for (k = 0; k < sigs_algs_len; k++) {
+        const char *sig_name = sigs_algname[k];
+
+        if (!sigs_doit[k] || !do_sigs)
+            continue;
+        if (testnum && !mr) {
+            printf("%31skeygen     signs    verify keygens/s    sign/s  verify/s\n", " ");
+            testnum = 0;
+        }
+        if (mr)
+            printf("+F10:%u:%f:%f:%f\n",
+                   k, sigs_results[k][0], sigs_results[k][1],
+                   sigs_results[k][2]);
+        else
+            printf("%27s %8.6fs %8.6fs %8.6fs %9.1f %9.1f %9.1f\n", sig_name,
+                   1.0 / sigs_results[k][0], 1.0 / sigs_results[k][1],
+                   1.0 / sigs_results[k][2], sigs_results[k][0],
+                   sigs_results[k][1], sigs_results[k][2]);
+    }
     ret = 0;
 
  end:
@@ -3393,11 +4208,29 @@ skip_hmac:
             EVP_PKEY_free(loopargs[i].sm2_pkey[k]);
         }
 #endif
+        for (k = 0; k < kems_algs_len; k++) {
+            EVP_PKEY_CTX_free(loopargs[i].kem_gen_ctx[k]);
+            EVP_PKEY_CTX_free(loopargs[i].kem_encaps_ctx[k]);
+            EVP_PKEY_CTX_free(loopargs[i].kem_decaps_ctx[k]);
+            OPENSSL_free(loopargs[i].kem_out[k]);
+            OPENSSL_free(loopargs[i].kem_send_secret[k]);
+            OPENSSL_free(loopargs[i].kem_rcv_secret[k]);
+        }
+        for (k = 0; k < sigs_algs_len; k++) {
+            EVP_PKEY_CTX_free(loopargs[i].sig_gen_ctx[k]);
+            EVP_PKEY_CTX_free(loopargs[i].sig_sign_ctx[k]);
+            EVP_PKEY_CTX_free(loopargs[i].sig_verify_ctx[k]);
+            OPENSSL_free(loopargs[i].sig_sig[k]);
+        }
         OPENSSL_free(loopargs[i].secret_a);
         OPENSSL_free(loopargs[i].secret_b);
     }
     OPENSSL_free(evp_hmac_name);
     OPENSSL_free(evp_cmac_name);
+    for (k = 0; k < kems_algs_len; k++)
+        OPENSSL_free(kems_algname[k]);
+    for (k = 0; k < sigs_algs_len; k++)
+        OPENSSL_free(sigs_algname[k]);
 
     if (async_jobs > 0) {
         for (i = 0; i < loopargs_len; i++)
@@ -3436,6 +4269,17 @@ static void pkey_print_message(const char *str, const char *str2, long num,
     alarm(tm);
 }
 
+static void kskey_print_message(const char *str, const char *str2,
+                                long num, int tm)
+{
+    BIO_printf(bio_err,
+               mr ? "+DTP:%s:%s:%d\n"
+               : "Doing %s %s's for %ds: ", str, str2, tm);
+    (void)BIO_flush(bio_err);
+    run = 1;
+    alarm(tm);
+}
+
 static void print_result(int alg, int run_no, int count, double time_used)
 {
     if (count == -1) {
@@ -3639,6 +4483,30 @@ static int do_multi(int multi, int size_num)
                     ffdh_results[k][0] += d;
                 }
 # endif /* OPENSSL_NO_DH */
+            } else if (CHECK_AND_SKIP_PREFIX(p, "+F9:")) {
+                tk = sstrsep(&p, sep);
+                if (strtoint(tk, 0, OSSL_NELEM(kems_results), &k)) {
+                    d = atof(sstrsep(&p, sep));
+                    kems_results[k][0] += d;
+
+                    d = atof(sstrsep(&p, sep));
+                    kems_results[k][1] += d;
+
+                    d = atof(sstrsep(&p, sep));
+                    kems_results[k][2] += d;
+                }
+            } else if (CHECK_AND_SKIP_PREFIX(p, "+F10:")) {
+                tk = sstrsep(&p, sep);
+                if (strtoint(tk, 0, OSSL_NELEM(sigs_results), &k)) {
+                    d = atof(sstrsep(&p, sep));
+                    sigs_results[k][0] += d;
+
+                    d = atof(sstrsep(&p, sep));
+                    sigs_results[k][1] += d;
+
+                    d = atof(sstrsep(&p, sep));
+                    sigs_results[k][2] += d;
+                }
             } else if (!HAS_PREFIX(buf, "+H:")) {
                 BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf,
                            n);
index ab76ca6f137b614e7ad513e3a41d9664e20067aa..38e95720a31dff5f765d7839d150f36feea5ffbe 100644 (file)
@@ -16,6 +16,8 @@ B<openssl speed>
 [B<-cmac> I<algo>]
 [B<-mb>]
 [B<-aead>]
+[B<-kem-algorithms>]
+[B<-signature-algorithms>]
 [B<-multi> I<num>]
 [B<-async_jobs> I<num>]
 [B<-misalign> I<num>]
@@ -97,6 +99,14 @@ Enable multi-block mode on EVP-named cipher.
 
 Benchmark EVP-named AEAD cipher in TLS-like sequence.
 
+=item B<-kem-algorithms>
+
+Benchmark KEM algorithms: key generation, encapsulation, decapsulation.
+
+=item B<-signature-algorithms>
+
+Benchmark signature algorithms: key generation, signature, verification.
+
 =item B<-primes> I<num>
 
 Generate a I<num>-prime RSA key and use it to run the benchmarks. This option