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)
47 if(!(ctx = EVP_PKEY_CTX_new(key1, NULL)))
51 EVP_PKEY_keygen_init(ctx);
52 if(ERR_peek_last_error())
56 if(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", param) <= 0)
60 if(EVP_PKEY_keygen(ctx, &newkey) <= 0)
66 EVP_PKEY_CTX_free(ctx);
71 void usage(char *name)
73 fprintf(stderr, "usage: %s [-l data_len] [-c cycles]\n", name);
77 int main(int argc, char **argv)
79 unsigned int data_len = 1;
80 unsigned int cycles = 100;
82 clockid_t clock_type = CLOCK_MONOTONIC;
83 int test, test_count = 0;
86 while((option = getopt(argc, argv, "l:c:C")) >= 0)
88 if(option == ':') option = optopt;
89 if(optarg && (optarg[0] == '-')) { optind--; optarg = NULL; }
93 data_len = atoi(optarg);
96 cycles = atoi(optarg);
99 clock_type = CLOCK_PROCESS_CPUTIME_ID;
106 if (optind < argc) usage(argv[0]);
107 if (cycles < 100) { printf("cycles too low\n"); exit(1); }
109 OPENSSL_add_all_algorithms_conf();
110 ERR_load_crypto_strings();
112 for (test = 0; tests[test]; test += 3) {
113 double diff[2]; /* sign, verify */
114 const char *digest = tests[test];
115 const char *algo = tests[test + 1];
116 const char *param = tests[test + 2];
117 const EVP_MD *mdtype;
120 unsigned char *sigbuf;
125 md_ctx = EVP_MD_CTX_new();
126 mdtype = EVP_get_digestbyname(digest);
129 pkey = create_key(algo, param);
130 data = (unsigned char *) malloc(data_len);
137 siglen = EVP_PKEY_size(pkey);
138 sigbuf = malloc(siglen * cycles);
140 fprintf(stderr, "No tests were run, malloc failure.\n");
144 for (pass = 0; pass < 2; pass++) {
146 struct timeval debut, fin, delta;
150 clock_gettime(clock_type, &ts);
151 TIMESPEC_TO_TIMEVAL(&debut, &ts);
153 if (pass == 0) { /* sign */
154 for (i = 0; i < cycles; i++) {
155 EVP_SignInit(md_ctx, mdtype);
156 err = EVP_SignUpdate(md_ctx, data, data_len)
157 && EVP_SignFinal(md_ctx, &sigbuf[siglen * i],
158 (unsigned int *)&siglen, pkey);
161 EVP_MD_CTX_reset(md_ctx);
163 } else { /* verify */
164 for (i = 0; i < cycles; i++) {
165 EVP_VerifyInit(md_ctx, mdtype);
166 err = EVP_VerifyUpdate(md_ctx, data, data_len)
167 && EVP_VerifyFinal(md_ctx, &sigbuf[siglen * i],
169 EVP_MD_CTX_reset(md_ctx);
175 clock_gettime(clock_type, &ts);
176 TIMESPEC_TO_TIMEVAL(&fin, &ts);
177 timersub(&fin, &debut, &delta);
178 diff[pass] = (double)delta.tv_sec + (double)delta.tv_usec / 1000000;
180 printf("\r%s %s: sign: %.1f/s, verify: %.1f/s\n", algo, param,
181 (double)cycles / diff[0], (double)cycles / diff[1]);
188 fprintf(stderr, "No tests were run, something is wrong.\n");