1 /**********************************************************************
2 * Simple benchmarking for gost-engine *
4 * Copyright (c) 2018 Cryptocom LTD *
5 * Copyright (c) 2018 <vt@altlinux.org>. *
6 * This file is distributed under the same license as OpenSSL *
7 **********************************************************************/
15 #include <openssl/rand.h>
16 #include <openssl/conf.h>
17 #include <openssl/err.h>
18 #include <openssl/evp.h>
19 #include <openssl/pem.h>
20 #include <openssl/engine.h>
22 const char *tests[] = {
23 "md_gost12_256", "gost2012_256", "A",
24 "md_gost12_256", "gost2012_256", "B",
25 "md_gost12_256", "gost2012_256", "C",
26 "md_gost12_256", "gost2012_256", "TCA",
27 "md_gost12_256", "gost2012_256", "TCB",
28 "md_gost12_256", "gost2012_256", "TCC",
29 "md_gost12_256", "gost2012_256", "TCD",
31 "md_gost12_512", "gost2012_512", "A",
32 "md_gost12_512", "gost2012_512", "B",
33 "md_gost12_512", "gost2012_512", "C",
38 static EVP_PKEY *create_key(const char *algname, const char *param)
40 EVP_PKEY *key1 = EVP_PKEY_new(), *newkey = NULL;
41 EVP_PKEY_CTX *ctx = NULL;
43 if (EVP_PKEY_set_type_str(key1, algname, strlen(algname)) <= 0)
46 if (!(ctx = EVP_PKEY_CTX_new(key1, NULL)))
49 if (EVP_PKEY_keygen_init(ctx) == 0)
52 if (ERR_peek_last_error())
55 if (EVP_PKEY_CTX_ctrl_str(ctx, "paramset", param) <= 0)
58 if (EVP_PKEY_keygen(ctx, &newkey) <= 0)
63 EVP_PKEY_CTX_free(ctx);
68 void usage(char *name)
70 fprintf(stderr, "usage: %s [-l data_len] [-c cycles]\n", name);
74 int main(int argc, char **argv)
76 unsigned int data_len = 1;
77 unsigned int cycles = 100;
79 clockid_t clock_type = CLOCK_MONOTONIC;
80 int test, test_count = 0;
83 while((option = getopt(argc, argv, "l:c:C")) >= 0)
88 data_len = atoi(optarg);
91 cycles = atoi(optarg);
94 clock_type = CLOCK_PROCESS_CPUTIME_ID;
101 if (optind < argc) usage(argv[0]);
102 if (cycles < 100) { printf("cycles too low\n"); exit(1); }
104 OPENSSL_add_all_algorithms_conf();
105 ERR_load_crypto_strings();
107 for (test = 0; tests[test]; test += 3) {
108 double diff[2]; /* sign, verify */
109 const char *digest = tests[test];
110 const char *algo = tests[test + 1];
111 const char *param = tests[test + 2];
112 const EVP_MD *mdtype;
115 unsigned char *sigbuf;
120 md_ctx = EVP_MD_CTX_new();
121 mdtype = EVP_get_digestbyname(digest);
124 pkey = create_key(algo, param);
125 data = (unsigned char *) malloc(data_len);
132 siglen = EVP_PKEY_size(pkey);
133 sigbuf = malloc(siglen * cycles);
135 fprintf(stderr, "No tests were run, malloc failure.\n");
139 for (pass = 0; pass < 2; pass++) {
141 struct timeval debut, fin, delta;
145 clock_gettime(clock_type, &ts);
146 TIMESPEC_TO_TIMEVAL(&debut, &ts);
148 if (pass == 0) { /* sign */
149 for (i = 0; i < cycles; i++) {
150 EVP_SignInit(md_ctx, mdtype);
151 err = EVP_SignUpdate(md_ctx, data, data_len)
152 && EVP_SignFinal(md_ctx, &sigbuf[siglen * i],
153 (unsigned int *)&siglen, pkey);
156 EVP_MD_CTX_reset(md_ctx);
158 } else { /* verify */
159 for (i = 0; i < cycles; i++) {
160 EVP_VerifyInit(md_ctx, mdtype);
161 err = EVP_VerifyUpdate(md_ctx, data, data_len)
162 && EVP_VerifyFinal(md_ctx, &sigbuf[siglen * i],
164 EVP_MD_CTX_reset(md_ctx);
170 clock_gettime(clock_type, &ts);
171 TIMESPEC_TO_TIMEVAL(&fin, &ts);
172 timersub(&fin, &debut, &delta);
173 diff[pass] = (double)delta.tv_sec + (double)delta.tv_usec / 1000000;
175 printf("\r%s %s: sign: %.1f/s, verify: %.1f/s\n", algo, param,
176 (double)cycles / diff[0], (double)cycles / diff[1]);
183 fprintf(stderr, "No tests were run, something is wrong.\n");