Add CMAC speed measurements
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Wed, 10 Apr 2019 20:44:41 +0000 (22:44 +0200)
committerBernd Edlinger <bernd.edlinger@hotmail.de>
Fri, 12 Apr 2019 11:52:43 +0000 (13:52 +0200)
usage: openssl speed -cmac aes128

Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/8721)

apps/speed.c
doc/man1/speed.pod

index 5674e3248d7c0fde8ecf02f88439cca461182164..e9ed8b54f791c6a505edbba5cba4b7dc446292b0 100644 (file)
@@ -57,6 +57,9 @@
 # include <openssl/md5.h>
 #endif
 #include <openssl/hmac.h>
+#ifndef OPENSSL_NO_CMAC
+#include <openssl/cmac.h>
+#endif
 #include <openssl/sha.h>
 #ifndef OPENSSL_NO_RMD160
 # include <openssl/ripemd.h>
@@ -300,7 +303,7 @@ typedef enum OPTION_choice {
     OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
     OPT_ELAPSED, OPT_EVP, OPT_HMAC, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
     OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM,
-    OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD
+    OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD, OPT_CMAC
 } OPTION_CHOICE;
 
 const OPTIONS speed_options[] = {
@@ -309,6 +312,9 @@ const OPTIONS speed_options[] = {
     {"help", OPT_HELP, '-', "Display this summary"},
     {"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
     {"hmac", OPT_HMAC, 's', "HMAC using EVP-named digest"},
+#ifndef OPENSSL_NO_CMAC
+    {"cmac", OPT_CMAC, 's', "CMAC using EVP-named cipher"},
+#endif
     {"decrypt", OPT_DECRYPT, '-',
      "Time decryption instead of encryption (only EVP)"},
     {"aead", OPT_AEAD, '-',
@@ -371,6 +377,7 @@ const OPTIONS speed_options[] = {
 #define D_GHASH         29
 #define D_RAND          30
 #define D_EVP_HMAC      31
+#define D_EVP_CMAC      32
 
 /* name of algorithms to test */
 static const char *names[] = {
@@ -381,7 +388,7 @@ static const char *names[] = {
     "camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc",
     "evp", "sha256", "sha512", "whirlpool",
     "aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash",
-    "rand", "hmac"
+    "rand", "hmac", "cmac"
 };
 #define ALGOR_NUM       OSSL_NELEM(names)
 
@@ -629,6 +636,9 @@ typedef struct loopargs_st {
 #endif
     EVP_CIPHER_CTX *ctx;
     HMAC_CTX *hctx;
+#ifndef OPENSSL_NO_CMAC
+    CMAC_CTX *cmac_ctx;
+#endif
     GCM128_CONTEXT *gcm_ctx;
 } loopargs_t;
 static int run_benchmark(int async_jobs, int (*loop_function) (void *),
@@ -1064,6 +1074,33 @@ static int EVP_HMAC_loop(void *args)
     return count;
 }
 
+#ifndef OPENSSL_NO_CMAC
+static const EVP_CIPHER *evp_cmac_cipher = NULL;
+static char *evp_cmac_name = NULL;
+
+static int EVP_CMAC_loop(void *args)
+{
+    loopargs_t *tempargs = *(loopargs_t **) args;
+    unsigned char *buf = tempargs->buf;
+    CMAC_CTX *cmac_ctx = tempargs->cmac_ctx;
+    static const char key[16] = "This is a key...";
+    unsigned char mac[16];
+    size_t len = sizeof(mac);
+    int count;
+#ifndef SIGALRM
+    int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
+#endif
+
+    for (count = 0; COND(nb_iter); count++) {
+        if (!CMAC_Init(cmac_ctx, key, sizeof(key), evp_cmac_cipher, NULL)
+                || !CMAC_Update(cmac_ctx, buf, lengths[testnum])
+                || !CMAC_Final(cmac_ctx, mac, &len))
+            return -1;
+    }
+    return count;
+}
+#endif
+
 #ifndef OPENSSL_NO_RSA
 static long rsa_c[RSA_NUM][2];  /* # RSA iteration test */
 
@@ -1610,6 +1647,17 @@ int speed_main(int argc, char **argv)
             }
             doit[D_EVP_HMAC] = 1;
             break;
+        case OPT_CMAC:
+#ifndef OPENSSL_NO_CMAC
+            evp_cmac_cipher = EVP_get_cipherbyname(opt_arg());
+            if (evp_cmac_cipher == NULL) {
+                BIO_printf(bio_err, "%s: %s is an unknown cipher\n",
+                           prog, opt_arg());
+                goto end;
+            }
+            doit[D_EVP_CMAC] = 1;
+#endif
+            break;
         case OPT_DECRYPT:
             decrypt = 1;
             break;
@@ -1848,9 +1896,9 @@ 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_EVP_HMAC]) {
+    if (argc == 0 && !doit[D_EVP] && !doit[D_EVP_HMAC] && !doit[D_EVP_CMAC]) {
         for (i = 0; i < ALGOR_NUM; i++)
-            if (i != D_EVP && i != D_EVP_HMAC)
+            if (i != D_EVP && i != D_EVP_HMAC && i != D_EVP_CMAC)
                 doit[i] = 1;
 #ifndef OPENSSL_NO_RSA
         for (i = 0; i < RSA_NUM; i++)
@@ -2719,6 +2767,36 @@ int speed_main(int argc, char **argv)
         }
     }
 
+#ifndef OPENSSL_NO_CMAC
+    if (doit[D_EVP_CMAC]) {
+        if (evp_cmac_cipher != NULL) {
+            const char *cipher_name = OBJ_nid2ln(EVP_CIPHER_type(evp_cmac_cipher));
+            evp_cmac_name = app_malloc(sizeof("CMAC()") + strlen(cipher_name),
+                                       "CMAC name");
+            sprintf(evp_cmac_name, "CMAC(%s)", cipher_name);
+            names[D_EVP_CMAC] = evp_cmac_name;
+
+            for (i = 0; i < loopargs_len; i++) {
+                loopargs[i].cmac_ctx = CMAC_CTX_new();
+                if (loopargs[i].cmac_ctx == NULL) {
+                    BIO_printf(bio_err, "CMAC malloc failure, exiting...");
+                    exit(1);
+                }
+            }
+            for (testnum = 0; testnum < size_num; testnum++) {
+                print_message(names[D_EVP_CMAC], save_count, lengths[testnum],
+                              seconds.sym);
+                Time_F(START);
+                count = run_benchmark(async_jobs, EVP_CMAC_loop, loopargs);
+                d = Time_F(STOP);
+                print_result(D_EVP_CMAC, testnum, count, d);
+            }
+            for (i = 0; i < loopargs_len; i++)
+                CMAC_CTX_free(loopargs[i].cmac_ctx);
+        }
+    }
+#endif
+
     for (i = 0; i < loopargs_len; i++)
         if (RAND_bytes(loopargs[i].buf, 36) <= 0)
             goto end;
@@ -3418,6 +3496,9 @@ int speed_main(int argc, char **argv)
 #endif
     }
     OPENSSL_free(evp_hmac_name);
+#ifndef OPENSSL_NO_CMAC
+    OPENSSL_free(evp_cmac_name);
+#endif
 
     if (async_jobs > 0) {
         for (i = 0; i < loopargs_len; i++)
index e164c6144478e6c8890742469d8ac6a259b5ce4b..1cb4494e760dfa95437a0258eae168ad6a15755b 100644 (file)
@@ -13,6 +13,7 @@ B<openssl speed>
 [B<-elapsed>]
 [B<-evp algo>]
 [B<-hmac algo>]
+[B<-cmac algo>]
 [B<-decrypt>]
 [B<-rand file...>]
 [B<-writerand file>]
@@ -60,6 +61,10 @@ aes-128-cbc-hmac-sha1, then B<-mb> will time multi-buffer operation.
 
 Time the HMAC algorithm using the specified message digest.
 
+=item B<-cmac cipher>
+
+Time the CMAC algorithm using the specified cipher e.g. B<speed -cmac aes128>.
+
 =item B<-decrypt>
 
 Time the decryption instead of encryption. Affects only the EVP testing.