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",
27 "md_gost12_512", "gost2012_512", "A",
28 "md_gost12_512", "gost2012_512", "B",
33 static EVP_PKEY *create_key(const char *algname, const char *param)
35 EVP_PKEY *key1 = EVP_PKEY_new(), *newkey = NULL;
36 EVP_PKEY_CTX *ctx = NULL;
38 if(EVP_PKEY_set_type_str(key1, algname, strlen(algname)) <= 0)
42 if(!(ctx = EVP_PKEY_CTX_new(key1, NULL)))
46 EVP_PKEY_keygen_init(ctx);
47 if(ERR_peek_last_error())
51 if(EVP_PKEY_CTX_ctrl_str(ctx, "paramset", param) <= 0)
55 if(EVP_PKEY_keygen(ctx, &newkey) <= 0)
61 EVP_PKEY_CTX_free(ctx);
66 void usage(char *name)
68 fprintf(stderr, "usage: %s [-l data_len] [-c cycles]\n", name);
72 int main(int argc, char **argv)
74 unsigned int data_len = 1;
75 unsigned int cycles = 100;
77 clockid_t clock_type = CLOCK_MONOTONIC;
78 int test, test_count = 0;
81 while((option = getopt(argc, argv, "l:c:C")) >= 0)
83 if(option == ':') option = optopt;
84 if(optarg && (optarg[0] == '-')) { optind--; optarg = NULL; }
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 for (pass = 0; pass < 2; pass++) {
137 struct timeval debut, fin, delta;
141 clock_gettime(clock_type, &ts);
142 TIMESPEC_TO_TIMEVAL(&debut, &ts);
144 if (pass == 0) { /* sign */
145 for (i = 0; i < cycles; i++) {
146 EVP_SignInit(md_ctx, mdtype);
147 EVP_SignUpdate(md_ctx, data, data_len);
148 err = EVP_SignFinal(md_ctx, &sigbuf[siglen * i],
149 (unsigned int *)&siglen, pkey);
152 EVP_MD_CTX_reset(md_ctx);
154 } else { /* verify */
155 for (i = 0; i < cycles; i++) {
156 EVP_VerifyInit(md_ctx, mdtype);
157 EVP_VerifyUpdate(md_ctx, data, data_len);
158 err = EVP_VerifyFinal(md_ctx, &sigbuf[siglen * i],
160 EVP_MD_CTX_reset(md_ctx);
166 clock_gettime(clock_type, &ts);
167 TIMESPEC_TO_TIMEVAL(&fin, &ts);
168 timersub(&fin, &debut, &delta);
169 diff[pass] = (double)delta.tv_sec + (double)delta.tv_usec / 1000000;
171 printf("\r%s %s: sign: %.1f/s, verify: %.1f/s\n", algo, param,
172 (double)cycles / diff[0], (double)cycles / diff[1]);
179 fprintf(stderr, "No tests were run, something is wrong.\n");