1
/* hogweed-benchmark.c */
3
/* nettle, low-level cryptographics library
5
* Copyright (C) 2013 Niels Möller
7
* The nettle library is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU Lesser General Public License as published by
9
* the Free Software Foundation; either version 2.1 of the License, or (at your
10
* option) any later version.
12
* The nettle library is distributed in the hope that it will be useful, but
13
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15
* License for more details.
17
* You should have received a copy of the GNU Lesser General Public License
18
* along with the nettle library; see the file COPYING.LIB. If not, write to
19
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42
#include "nettle-meta.h"
44
#include "knuth-lfib.h"
47
#include "../ecc-internal.h"
48
#include "../gmp-glue.h"
51
#include <openssl/ec.h>
52
#include <openssl/ecdsa.h>
53
#include <openssl/objects.h>
56
#define BENCH_INTERVAL 0.1
58
static void NORETURN PRINTF_STYLE(1,2)
59
die(const char *format, ...)
62
va_start(args, format);
63
vfprintf(stderr, format, args);
72
void *p = malloc (size);
75
fprintf (stderr, "Virtual memory exhausted\n");
82
hash_string (const struct nettle_hash *hash,
83
unsigned length, const char *s)
85
void *ctx = xalloc (hash->context_size);
86
uint8_t *digest = xalloc (hash->digest_size);
88
hash->update (ctx, length, s);
89
hash->digest (ctx, hash->digest_size, digest);
98
void *(*init) (unsigned size);
99
void (*sign) (void *);
100
void (*verify)(void *);
101
void (*clear) (void *);
104
/* Returns second per function call */
106
time_function(void (*f)(void *arg), void *arg)
118
for (i = 0; i < ncalls; i++)
120
elapsed = time_end();
121
if (elapsed > BENCH_INTERVAL)
123
else if (elapsed < BENCH_INTERVAL / 10)
128
return elapsed / ncalls;
132
bench_alg (const struct alg *alg)
138
ctx = alg->init(alg->size);
140
sign = time_function (alg->sign, ctx);
141
verify = time_function (alg->verify, ctx);
145
printf("%15s %4d %9.4f %9.4f\n",
146
alg->name, alg->size, 1e-3/sign, 1e-3/verify);
151
struct rsa_public_key pub;
152
struct rsa_private_key key;
158
bench_rsa_init (unsigned size)
161
"{KDExOnByaXZhdGUta2V5KDE0OnJzYS1wa2NzMS1zaGExKDE6bjEyOToA90+K5EmjbFJBeJD"
162
" xP2KD2Df+0Twc9425uB+vhqTrVijtd2PnwEQDfR2VoducgkKcXJzYYyCNILQJbFAi2Km/sD"
163
" jImERBqDtaI217Ze+tOKEmImexYTAgFuqEptp2F3M4DqgRQ7s/3nJQ/bPE5Hfi1OZhJSShu"
164
" I80ATTU4fUgrPspKDE6ZTM6AQABKSgxOmQxMjk6APAhKckzvxxkWfHJOpXDACWnaSKcbbvo"
165
" vtWK3pGr/F2ya7CrLtE+uOx5F1sLs9G+/7flCy5k4uNILIYg4VTirZ1zQ8fNKPrjK1VMRls"
166
" JiRRU/0VAs9d7HdncJfs6rbvRQbCRSRYURo4hWir3Lq8V3UUQVBprc4dO+uWmplvwQ5qxKS"
167
" gxOnA2NToA+8aIVkdbk8Jg8dJOuzc7m/hZnwkKSs6eVDw4N/2T0CJKGJYT+B3Ct+fPkxhUR"
168
" ggd2DQ9OpkTra7SXHTNkzdPVSkoMTpxNjU6APt11P8vXNnGYF0OC/cPsR8zhSYuFmtRuX6G"
169
" ES+DdG0VCU07UeNQkok1UoW5sXqY0IGr1jkJq8AMSgKoNbLQ6w8pKDE6YTY0Ohzkxsan/8F"
170
" wQDHgQbrIduXKVXaj0fONzKu8EXOTfUAYf0pdBsOlnq/+QVsPIrS6v7oNHK253YFEG84SdX"
171
" kcktUpKDE6YjY1OgCR+cRtY3RWY+f6/TWK9gwPndv03xpasLWrMm71ky1aSbT9pasS9+opR"
172
" tAiGzthfSbFsBiLQgb3VOr+AeIybT+XKSgxOmM2NDojigqARWN5u1CVDVuD2L2ManpoGiM6"
173
" kQ6FaJjqRjxeRRKFrQxGJa9tM1hqStxokC1oJidgaOLGnn60iwzToug9KSkp}";
176
"{KDExOnByaXZhdGUta2V5KDE0OnJzYS1wa2NzMS1zaGExKDE6bjI1NzoAtxWXiglIdunDK48"
177
" 8I0vW0wTqnh/riW9pLk8n1F8MUPBFdhvkkl0bDQqSJPUvSHy+w4fLVwcEzeI4qFyo3b2Avz"
178
" JK20MFbt/WfHD1TbxuK8rNqXyqmqjJ9vgjtV9nPzAz7CM9ogs3/RJHpcfZPQF15ifizleUZ"
179
" aQT0GAXHZL7cePj10yGI2u3hgTkokVzdNC/1T34guKYpErg0pt0B/KejWpsFTb84z3tkR+B"
180
" YVx07p/OoByZwoABgncS/uALl31fRS8jyJ2JqUiZOqe7XoO9hkDHYNCWUGUfNGQ7ZgVp9+e"
181
" NQpracSjrp6Jnrj7r/oxJUx5ZDVNi18AzQadE/oKOrSkoMTplMzoBAAEpKDE6ZDI1NjogBT"
182
" C5vaHk2kF+LtDvw2XRBj0aZq7FHK0ioklvBSicR0l+vKYfSxVeFIk22YLphJfAjtFraRjYA"
183
" Uaze3E1Rt1rkxoweupKV++lWAQvElOaaR/LErirz/Vysjdck1D1ZjLOi+NNofSq2DWbsvY1"
184
" iznZhQRP3lVf6XBls0iXrYs4gb0pBZqXLQW+j9Ihx6eantf1/6ZMKPgCkzcAZ0ABsCfaFSg"
185
" ouNCzilblsgFEspEbb8QqrNQoStS3F/gMwWgDsr3+vQzBqt+7ykWoCJ9wctbYy9kEPq+hX3"
186
" GP0hG6HdS81r9E8pgdf3wloNNMzYUHwn7poXGpOi8tG0pmR56TqD/BKSgxOnAxMjk6AN4AJ"
187
" TiGPm9We2ga3Y0jpTfA3mWpUbhYgaXYLWA1/riniwq16fqxRIkWQT/O2KKpBVe6WSvNYq9u"
188
" lM8N6bdPtDytJs6AOXy0X5vtJ953ZYVMhHbhmUxhIL9I+s0O1+LxMF8b9U4CrFyaTxd8Un/"
189
" FXP1BvYJRrkoup6HYvOlGx36lKSgxOnExMjk6ANMfrfH6z/3o7K56aW6kSiloDDbKZQ0+W5"
190
" 8LzP2ZOBLf6LX6jLhN3olU1Z0KGTM0S/1AxvwGjuRqhu+LcOJ7oUCUH3uusR5c5nSnArYPq"
191
" +0wbco4BQngot/HmGN7U0EDsIWqPt/qoa/b8bCk+TOwJlknNq/PnZU26SPj48XS05lpKSgx"
192
" OmExMjk6AJM2n3gLNW3ZeH5BindkktQU9qWNkV5geqDCaNyrEZ3bpI1WsrEGSj9p3Zz1ipz"
193
" a3msdbLJqQS26c72WKUzg8tFltR0s1HJInjolGtIgdNbfNdwrn9+RbQjL2VyPokOg0wXO4W"
194
" 14wlmqDhax33dRJmfe50964MvaglkGA8fhorrtKSgxOmIxMjk6AKMe+vrX2xRHf3dfxU5jS"
195
" ZmsdqNuxZzx7UB5kazvUU/kCJ1yNH/CSoq5LULkpovVgFDwV84qEwWQ+SjkCBg1hWWsDJc3"
196
" ZkobZUQENigM+72LiYiQt/PlyHI2eRuEEdNN0nm0DFhdpQeHXLoq/RBerYJ8tdgpBYxgnMn"
197
" KLhaOykbhKSgxOmMxMjg6MVlKj2bjb7qFQVkLO1OPg28jSrtRpnQCR+qegN4ZmNam/qbest"
198
" 8yn0JQ6gxX7PvP382+jx7uHHWHYYqPq/Flf8gqtOOcjqS5TJgVHz3F3xHWquo1ZofGtCMro"
199
" Dd2c0xjRjIVGvLV6Ngs+HRdljRav40vRpTyEoEdlzHBQiILesopKSk=}";
202
struct sexp_iterator i;
206
ctx = xalloc(sizeof(*ctx));
208
rsa_public_key_init (&ctx->pub);
209
rsa_private_key_init (&ctx->key);
212
/* NOTE: Base64-decodes the strings in-place */
214
res = sexp_transport_iterator_first (&i, sizeof(rsa1024) - 1, rsa1024);
215
else if (size == 2048)
216
res = sexp_transport_iterator_first (&i, sizeof(rsa2048) - 1, rsa2048);
218
die ("Internal error.\n");
221
&& sexp_iterator_check_type (&i, "private-key")
222
&& sexp_iterator_check_type (&i, "rsa-pkcs1-sha1")
223
&& rsa_keypair_from_sexp_alist (&ctx->pub, &ctx->key, 0, &i)))
224
die ("Internal error.\n");
226
ctx->digest = hash_string (&nettle_sha256, 3, "foo");
228
rsa_sha256_sign_digest (&ctx->key, ctx->digest, ctx->s);
234
bench_rsa_sign (void *p)
236
struct rsa_ctx *ctx = (struct rsa_ctx *) p;
240
rsa_sha256_sign_digest (&ctx->key, ctx->digest, s);
245
bench_rsa_verify (void *p)
247
struct rsa_ctx *ctx = (struct rsa_ctx *) p;
248
int res = rsa_sha256_verify_digest (&ctx->pub, ctx->digest, ctx->s);
250
die ("Internal error, rsa_sha256_verify_digest failed.\n");
254
bench_rsa_clear (void *p)
256
struct rsa_ctx *ctx = (struct rsa_ctx *) p;
258
rsa_public_key_clear (&ctx->pub);
259
rsa_private_key_clear (&ctx->key);
268
struct dsa_public_key pub;
269
struct dsa_private_key key;
270
struct knuth_lfib_ctx lfib;
271
struct dsa_signature s;
276
bench_dsa_init (unsigned size)
279
struct sexp_iterator i;
282
"{KDExOnByaXZhdGUta2V5KDM6ZHNhKDE6cDEyOToA2q4hOXEClLMXXMOl9xaPcGC/GeGmCMv"
283
" VCaaW0uWc50DvvmJDPQPdCehyfZr/1dv2UDbx06TC7ls/IFd+BsDzGBRxqIQ44J20cn+0gt"
284
" NMIXAocE1QhCCFaT5gXrk8zMlqBEGaP3RdpgxNanEXkTj2Wma8r1GtrLX3HPafio62jicpK"
285
" DE6cTIxOgDN9pcW3exdVAesC9WsxwCGoJK24ykoMTpnMTI5OgCJr9DmKdiE0WJZB7HACESv"
286
" Tpg1qZgc8E15byQ+OsHUyOTRrJRTcrgKZJW7dFRJ9cXmyi7XYCd3bJtu/2HRHLY1vd4qMvU"
287
" 7Y8x08ooCoABGV7nGqcmdQfEho1OY6TZh2NikmPKZLeur3PZFpcZ8Dl+KVWtwC55plNC7Om"
288
" iAQy8MaCkoMTp5MTI5OgDakk0LOUQwzOKt9FHOBmBKrWsvTm7549eScTUqH4OMm3btjUsXz"
289
" MmlqEe+imwQCOW/AE3Xw9pXZeETWK0jlLe8k5vnKcNskerFwZ1eQKtOPPQty8IqQ9PEfF6B"
290
" 0oVQiJg2maHUDWFnDkIBd7ZR1z8FnZMUxH9mH4kEUo6YQgtCdykoMTp4MjA6cOl3ijiiMjI"
291
" pesFD8jxESWb2mn8pKSk=}";
293
ctx = xalloc(sizeof(*ctx));
295
dsa_public_key_init (&ctx->pub);
296
dsa_private_key_init (&ctx->key);
297
dsa_signature_init (&ctx->s);
298
knuth_lfib_init (&ctx->lfib, 1);
301
die ("Internal error.\n");
303
if (! (sexp_transport_iterator_first (&i, sizeof(dsa1024) - 1, dsa1024)
304
&& sexp_iterator_check_type (&i, "private-key")
305
&& sexp_iterator_check_type (&i, "dsa")
306
&& dsa_keypair_from_sexp_alist (&ctx->pub, &ctx->key, 0, DSA_SHA1_Q_BITS, &i)) )
307
die ("Internal error.\n");
309
ctx->digest = hash_string (&nettle_sha1, 3, "foo");
311
dsa_sha1_sign_digest (&ctx->pub, &ctx->key,
312
&ctx->lfib, (nettle_random_func *)knuth_lfib_random,
313
ctx->digest, &ctx->s);
319
bench_dsa_sign (void *p)
321
struct dsa_ctx *ctx = (struct dsa_ctx *) p;
322
struct dsa_signature s;
324
dsa_signature_init (&s);
325
dsa_sha1_sign_digest (&ctx->pub, &ctx->key,
326
&ctx->lfib, (nettle_random_func *)knuth_lfib_random,
328
dsa_signature_clear (&s);
332
bench_dsa_verify (void *p)
334
struct dsa_ctx *ctx = (struct dsa_ctx *) p;
335
int res = dsa_sha1_verify_digest (&ctx->pub, ctx->digest, &ctx->s);
337
die ("Internal error, dsa_sha1_verify_digest failed.\n");
341
bench_dsa_clear (void *p)
343
struct dsa_ctx *ctx = (struct dsa_ctx *) p;
344
dsa_public_key_clear (&ctx->pub);
345
dsa_private_key_clear (&ctx->key);
346
dsa_signature_clear (&ctx->s);
353
struct ecc_point pub;
354
struct ecc_scalar key;
355
struct knuth_lfib_ctx rctx;
356
unsigned digest_size;
358
struct dsa_signature s;
362
bench_ecdsa_init (unsigned size)
364
struct ecdsa_ctx *ctx;
365
const struct ecc_curve *ecc;
372
ctx = xalloc (sizeof(*ctx));
374
dsa_signature_init (&ctx->s);
375
knuth_lfib_init (&ctx->rctx, 17);
380
ecc = &nettle_secp_192r1;
381
xs = "8e8e07360350fb6b7ad8370cfd32fa8c6bba785e6e200599";
382
ys = "7f82ddb58a43d59ff8dc66053002b918b99bd01bd68d6736";
383
zs = "f2e620e086d658b4b507996988480917640e4dc107808bdd";
384
ctx->digest = hash_string (&nettle_sha1, 3, "abc");
385
ctx->digest_size = 20;
388
ecc = &nettle_secp_224r1;
389
xs = "993bf363f4f2bc0f255f22563980449164e9c894d9efd088d7b77334";
390
ys = "b75fff9849997d02d135140e4d0030944589586e22df1fc4b629082a";
391
zs = "cdfd01838247f5de3cc70b688418046f10a2bfaca6de9ec836d48c27";
392
ctx->digest = hash_string (&nettle_sha224, 3, "abc");
393
ctx->digest_size = 28;
398
ecc = &nettle_secp_256r1;
399
xs = "2442A5CC 0ECD015F A3CA31DC 8E2BBC70 BF42D60C BCA20085 E0822CB0 4235E970";
400
ys = "6FC98BD7 E50211A4 A27102FA 3549DF79 EBCB4BF2 46B80945 CDDFE7D5 09BBFD7D";
401
zs = "DC51D386 6A15BACD E33D96F9 92FCA99D A7E6EF09 34E70975 59C27F16 14C88A7F";
402
ctx->digest = hash_string (&nettle_sha256, 3, "abc");
403
ctx->digest_size = 32;
406
ecc = &nettle_secp_384r1;
407
xs = "96281BF8 DD5E0525 CA049C04 8D345D30 82968D10 FEDF5C5A CA0C64E6 465A97EA"
408
"5CE10C9D FEC21797 41571072 1F437922";
409
ys = "447688BA 94708EB6 E2E4D59F 6AB6D7ED FF9301D2 49FE49C3 3096655F 5D502FAD"
410
"3D383B91 C5E7EDAA 2B714CC9 9D5743CA";
411
zs = "0BEB6466 34BA8773 5D77AE48 09A0EBEA 865535DE 4C1E1DCB 692E8470 8E81A5AF"
412
"62E528C3 8B2A81B3 5309668D 73524D9F";
413
ctx->digest = hash_string (&nettle_sha384, 3, "abc");
414
ctx->digest_size = 48;
417
ecc = &nettle_secp_521r1;
418
xs = "0151518F 1AF0F563 517EDD54 85190DF9 5A4BF57B 5CBA4CF2 A9A3F647 4725A35F"
419
"7AFE0A6D DEB8BEDB CD6A197E 592D4018 8901CECD 650699C9 B5E456AE A5ADD190"
421
ys = "006F3B14 2EA1BFFF 7E2837AD 44C9E4FF 6D2D34C7 3184BBAD 90026DD5 E6E85317"
422
"D9DF45CA D7803C6C 20035B2F 3FF63AFF 4E1BA64D 1C077577 DA3F4286 C58F0AEA"
424
zs = "0065FDA3 409451DC AB0A0EAD 45495112 A3D813C1 7BFD34BD F8C1209D 7DF58491"
425
"20597779 060A7FF9 D704ADF7 8B570FFA D6F062E9 5C7E0C5D 5481C5B1 53B48B37"
428
ctx->digest = hash_string (&nettle_sha512, 3, "abc");
429
ctx->digest_size = 64;
432
die ("Internal error.\n");
434
ecc_point_init (&ctx->pub, ecc);
435
ecc_scalar_init (&ctx->key, ecc);
437
mpz_init_set_str (x, xs, 16);
438
mpz_init_set_str (y, ys, 16);
439
mpz_init_set_str (z, zs, 16);
441
ecc_point_set (&ctx->pub, x, y);
442
ecc_scalar_set (&ctx->key, z);
448
ecdsa_sign (&ctx->key,
449
&ctx->rctx, (nettle_random_func *) knuth_lfib_random,
450
ctx->digest_size, ctx->digest,
457
bench_ecdsa_sign (void *p)
459
struct ecdsa_ctx *ctx = (struct ecdsa_ctx *) p;
460
struct dsa_signature s;
462
dsa_signature_init (&s);
463
ecdsa_sign (&ctx->key,
464
&ctx->rctx, (nettle_random_func *) knuth_lfib_random,
465
ctx->digest_size, ctx->digest,
467
dsa_signature_clear (&s);
471
bench_ecdsa_verify (void *p)
473
struct ecdsa_ctx *ctx = (struct ecdsa_ctx *) p;
474
int res = ecdsa_verify (&ctx->pub,
475
ctx->digest_size, ctx->digest,
478
die ("Internal error, _ecdsa_verify failed.\n");
482
bench_ecdsa_clear (void *p)
484
struct ecdsa_ctx *ctx = (struct ecdsa_ctx *) p;
486
ecc_point_clear (&ctx->pub);
487
ecc_scalar_clear (&ctx->key);
488
dsa_signature_clear (&ctx->s);
498
ECDSA_SIG *signature;
499
unsigned digest_length;
504
bench_openssl_init (unsigned size)
506
struct openssl_ctx *ctx = xalloc (sizeof (*ctx));
508
/* Apparently, secp192r1 and secp256r1 are missing */
513
ctx->key = EC_KEY_new_by_curve_name (NID_secp192r1);
514
ctx->digest_length = 24; /* truncated */
515
ctx->digest = hash_string (&nettle_sha224, 3, "abc");
519
ctx->key = EC_KEY_new_by_curve_name (NID_secp224r1);
520
ctx->digest_length = SHA224_DIGEST_SIZE;
521
ctx->digest = hash_string (&nettle_sha224, 3, "abc");
525
ctx->key = EC_KEY_new_by_curve_name (NID_secp256r1);
526
ctx->digest_length = SHA256_DIGEST_SIZE;
527
ctx->digest = hash_string (&nettle_sha256, 3, "abc");
531
ctx->key = EC_KEY_new_by_curve_name (NID_secp384r1);
532
ctx->digest_length = SHA384_DIGEST_SIZE;
533
ctx->digest = hash_string (&nettle_sha384, 3, "abc");
536
ctx->key = EC_KEY_new_by_curve_name (NID_secp521r1);
537
ctx->digest_length = SHA512_DIGEST_SIZE;
538
ctx->digest = hash_string (&nettle_sha512, 3, "abc");
541
die ("Internal error.\n");
545
if (!EC_KEY_generate_key( ctx->key))
546
die ("Openssl EC_KEY_generate_key failed.\n");
548
ctx->signature = ECDSA_do_sign (ctx->digest, ctx->digest_length, ctx->key);
554
bench_openssl_sign (void *p)
556
const struct openssl_ctx *ctx = (const struct openssl_ctx *) p;
557
ECDSA_SIG *sig = ECDSA_do_sign (ctx->digest, ctx->digest_length, ctx->key);
558
ECDSA_SIG_free (sig);
562
bench_openssl_verify (void *p)
564
const struct openssl_ctx *ctx = (const struct openssl_ctx *) p;
565
int res = ECDSA_do_verify (ctx->digest, ctx->digest_length,
566
ctx->signature, ctx->key);
568
die ("Openssl ECDSA_do_verify failed.\n");
571
bench_openssl_clear (void *p)
573
struct openssl_ctx *ctx = (struct openssl_ctx *) p;
574
ECDSA_SIG_free (ctx->signature);
575
EC_KEY_free (ctx->key);
581
struct alg alg_list[] = {
582
{ "rsa", 1024, bench_rsa_init, bench_rsa_sign, bench_rsa_verify, bench_rsa_clear },
583
{ "rsa", 2048, bench_rsa_init, bench_rsa_sign, bench_rsa_verify, bench_rsa_clear },
584
{ "dsa", 1024, bench_dsa_init, bench_dsa_sign, bench_dsa_verify, bench_dsa_clear },
586
{ "dsa",2048, bench_dsa_init, bench_dsa_sign, bench_dsa_verify, bench_dsa_clear },
588
{ "ecdsa", 192, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
589
{ "ecdsa", 224, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
590
{ "ecdsa", 256, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
591
{ "ecdsa", 384, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
592
{ "ecdsa", 521, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
594
{ "ecdsa (openssl)", 224, bench_openssl_init, bench_openssl_sign, bench_openssl_verify, bench_openssl_clear },
595
{ "ecdsa (openssl)", 384, bench_openssl_init, bench_openssl_sign, bench_openssl_verify, bench_openssl_clear },
596
{ "ecdsa (openssl)", 521, bench_openssl_init, bench_openssl_sign, bench_openssl_verify, bench_openssl_clear },
600
#define numberof(x) (sizeof (x) / sizeof ((x)[0]))
603
main (int argc, char **argv)
605
const char *filter = NULL;
612
printf ("%15s %4s %9s %9s\n",
613
"name", "size", "sign/ms", "verify/ms");
615
for (i = 0; i < numberof(alg_list); i++)
616
if (!filter || strstr (alg_list[i].name, filter))
617
bench_alg (&alg_list[i]);