1 /* hogweed-benchmark.c
2
3 Copyright (C) 2013, 2014 Niels Möller
4
5 This file is part of GNU Nettle.
6
7 GNU Nettle is free software: you can redistribute it and/or
8 modify it under the terms of either:
9
10 * the GNU Lesser General Public License as published by the Free
11 Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13
14 or
15
16 * the GNU General Public License as published by the Free
17 Software Foundation; either version 2 of the License, or (at your
18 option) any later version.
19
20 or both in parallel, as here.
21
22 GNU Nettle is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 General Public License for more details.
26
27 You should have received copies of the GNU General Public License and
28 the GNU Lesser General Public License along with this program. If
29 not, see http://www.gnu.org/licenses/.
30 */
31
32 #if HAVE_CONFIG_H
33 # include "config.h"
34 #endif
35
36 #include <assert.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41
42 #include <errno.h>
43
44 #include <time.h>
45
46 #include "timing.h"
47
48 #include "dsa.h"
49 #include "rsa.h"
50 #include "eddsa.h"
51 #include "gostdsa.h"
52 #include "curve25519.h"
53 #include "curve448.h"
54
55 #include "nettle-meta.h"
56 #include "sexp.h"
57 #include "knuth-lfib.h"
58
59 #include "../ecdsa.h"
60 #include "../ecc-internal.h"
61 #include "../gmp-glue.h"
62
63 #if WITH_OPENSSL
64 #include <openssl/rsa.h>
65 #include <openssl/bn.h>
66 #include <openssl/ec.h>
67 #include <openssl/ecdsa.h>
68 #include <openssl/objects.h>
69 #endif
70
71 #define BENCH_INTERVAL 0.1
72
73 static void NORETURN PRINTF_STYLE(1,2)
die(const char * format,...)74 die(const char *format, ...)
75 {
76 va_list args;
77 va_start(args, format);
78 vfprintf(stderr, format, args);
79 va_end(args);
80
81 exit(EXIT_FAILURE);
82 }
83
84 static void *
xalloc(size_t size)85 xalloc (size_t size)
86 {
87 void *p = malloc (size);
88 if (!p)
89 {
90 fprintf (stderr, "Virtual memory exhausted\n");
91 abort ();
92 }
93 return p;
94 }
95
96 static uint8_t *
hash_string(const struct nettle_hash * hash,const char * s)97 hash_string (const struct nettle_hash *hash, const char *s)
98 {
99 void *ctx = xalloc (hash->context_size);
100 uint8_t *digest = xalloc (hash->digest_size);
101 hash->init (ctx);
102 hash->update (ctx, strlen(s), (const uint8_t *) s);
103 hash->digest (ctx, hash->digest_size, digest);
104 free (ctx);
105
106 return digest;
107 }
108
109 struct alg {
110 const char *name;
111 unsigned size;
112 void *(*init) (unsigned size);
113 void (*sign) (void *);
114 void (*verify)(void *);
115 void (*clear) (void *);
116 };
117
118 /* Returns second per function call */
119 static double
time_function(void (* f)(void * arg),void * arg)120 time_function(void (*f)(void *arg), void *arg)
121 {
122 unsigned ncalls;
123 double elapsed;
124
125 /* Warm up */
126 f(arg);
127 for (ncalls = 10 ;;)
128 {
129 unsigned i;
130
131 time_start();
132 for (i = 0; i < ncalls; i++)
133 f(arg);
134 elapsed = time_end();
135 if (elapsed > BENCH_INTERVAL)
136 break;
137 else if (elapsed < BENCH_INTERVAL / 10)
138 ncalls *= 10;
139 else
140 ncalls *= 2;
141 }
142 return elapsed / ncalls;
143 }
144
145 static void
bench_alg(const struct alg * alg)146 bench_alg (const struct alg *alg)
147 {
148 double sign;
149 double verify;
150 void *ctx;
151
152 ctx = alg->init(alg->size);
153 if (ctx == NULL)
154 {
155 printf("%16s %4d N/A\n", alg->name, alg->size);
156 return;
157 }
158
159 sign = time_function (alg->sign, ctx);
160 verify = time_function (alg->verify, ctx);
161
162 alg->clear (ctx);
163
164 printf("%16s %4d %9.4f %9.4f\n",
165 alg->name, alg->size, 1e-3/sign, 1e-3/verify);
166 }
167
168 struct rsa_ctx
169 {
170 struct rsa_public_key pub;
171 struct rsa_private_key key;
172 struct knuth_lfib_ctx lfib;
173 uint8_t *digest;
174 mpz_t s;
175 };
176
177 static void *
bench_rsa_init(unsigned size)178 bench_rsa_init (unsigned size)
179 {
180 unsigned char rsa1024[] =
181 "{KDExOnByaXZhdGUta2V5KDE0OnJzYS1wa2NzMS1zaGExKDE6bjEyOToA90+K5EmjbFJBeJD"
182 " xP2KD2Df+0Twc9425uB+vhqTrVijtd2PnwEQDfR2VoducgkKcXJzYYyCNILQJbFAi2Km/sD"
183 " jImERBqDtaI217Ze+tOKEmImexYTAgFuqEptp2F3M4DqgRQ7s/3nJQ/bPE5Hfi1OZhJSShu"
184 " I80ATTU4fUgrPspKDE6ZTM6AQABKSgxOmQxMjk6APAhKckzvxxkWfHJOpXDACWnaSKcbbvo"
185 " vtWK3pGr/F2ya7CrLtE+uOx5F1sLs9G+/7flCy5k4uNILIYg4VTirZ1zQ8fNKPrjK1VMRls"
186 " JiRRU/0VAs9d7HdncJfs6rbvRQbCRSRYURo4hWir3Lq8V3UUQVBprc4dO+uWmplvwQ5qxKS"
187 " gxOnA2NToA+8aIVkdbk8Jg8dJOuzc7m/hZnwkKSs6eVDw4N/2T0CJKGJYT+B3Ct+fPkxhUR"
188 " ggd2DQ9OpkTra7SXHTNkzdPVSkoMTpxNjU6APt11P8vXNnGYF0OC/cPsR8zhSYuFmtRuX6G"
189 " ES+DdG0VCU07UeNQkok1UoW5sXqY0IGr1jkJq8AMSgKoNbLQ6w8pKDE6YTY0Ohzkxsan/8F"
190 " wQDHgQbrIduXKVXaj0fONzKu8EXOTfUAYf0pdBsOlnq/+QVsPIrS6v7oNHK253YFEG84SdX"
191 " kcktUpKDE6YjY1OgCR+cRtY3RWY+f6/TWK9gwPndv03xpasLWrMm71ky1aSbT9pasS9+opR"
192 " tAiGzthfSbFsBiLQgb3VOr+AeIybT+XKSgxOmM2NDojigqARWN5u1CVDVuD2L2ManpoGiM6"
193 " kQ6FaJjqRjxeRRKFrQxGJa9tM1hqStxokC1oJidgaOLGnn60iwzToug9KSkp}";
194
195 unsigned char rsa2048[] =
196 "{KDExOnByaXZhdGUta2V5KDE0OnJzYS1wa2NzMS1zaGExKDE6bjI1NzoAtxWXiglIdunDK48"
197 " 8I0vW0wTqnh/riW9pLk8n1F8MUPBFdhvkkl0bDQqSJPUvSHy+w4fLVwcEzeI4qFyo3b2Avz"
198 " JK20MFbt/WfHD1TbxuK8rNqXyqmqjJ9vgjtV9nPzAz7CM9ogs3/RJHpcfZPQF15ifizleUZ"
199 " aQT0GAXHZL7cePj10yGI2u3hgTkokVzdNC/1T34guKYpErg0pt0B/KejWpsFTb84z3tkR+B"
200 " YVx07p/OoByZwoABgncS/uALl31fRS8jyJ2JqUiZOqe7XoO9hkDHYNCWUGUfNGQ7ZgVp9+e"
201 " NQpracSjrp6Jnrj7r/oxJUx5ZDVNi18AzQadE/oKOrSkoMTplMzoBAAEpKDE6ZDI1NjogBT"
202 " C5vaHk2kF+LtDvw2XRBj0aZq7FHK0ioklvBSicR0l+vKYfSxVeFIk22YLphJfAjtFraRjYA"
203 " Uaze3E1Rt1rkxoweupKV++lWAQvElOaaR/LErirz/Vysjdck1D1ZjLOi+NNofSq2DWbsvY1"
204 " iznZhQRP3lVf6XBls0iXrYs4gb0pBZqXLQW+j9Ihx6eantf1/6ZMKPgCkzcAZ0ABsCfaFSg"
205 " ouNCzilblsgFEspEbb8QqrNQoStS3F/gMwWgDsr3+vQzBqt+7ykWoCJ9wctbYy9kEPq+hX3"
206 " GP0hG6HdS81r9E8pgdf3wloNNMzYUHwn7poXGpOi8tG0pmR56TqD/BKSgxOnAxMjk6AN4AJ"
207 " TiGPm9We2ga3Y0jpTfA3mWpUbhYgaXYLWA1/riniwq16fqxRIkWQT/O2KKpBVe6WSvNYq9u"
208 " lM8N6bdPtDytJs6AOXy0X5vtJ953ZYVMhHbhmUxhIL9I+s0O1+LxMF8b9U4CrFyaTxd8Un/"
209 " FXP1BvYJRrkoup6HYvOlGx36lKSgxOnExMjk6ANMfrfH6z/3o7K56aW6kSiloDDbKZQ0+W5"
210 " 8LzP2ZOBLf6LX6jLhN3olU1Z0KGTM0S/1AxvwGjuRqhu+LcOJ7oUCUH3uusR5c5nSnArYPq"
211 " +0wbco4BQngot/HmGN7U0EDsIWqPt/qoa/b8bCk+TOwJlknNq/PnZU26SPj48XS05lpKSgx"
212 " OmExMjk6AJM2n3gLNW3ZeH5BindkktQU9qWNkV5geqDCaNyrEZ3bpI1WsrEGSj9p3Zz1ipz"
213 " a3msdbLJqQS26c72WKUzg8tFltR0s1HJInjolGtIgdNbfNdwrn9+RbQjL2VyPokOg0wXO4W"
214 " 14wlmqDhax33dRJmfe50964MvaglkGA8fhorrtKSgxOmIxMjk6AKMe+vrX2xRHf3dfxU5jS"
215 " ZmsdqNuxZzx7UB5kazvUU/kCJ1yNH/CSoq5LULkpovVgFDwV84qEwWQ+SjkCBg1hWWsDJc3"
216 " ZkobZUQENigM+72LiYiQt/PlyHI2eRuEEdNN0nm0DFhdpQeHXLoq/RBerYJ8tdgpBYxgnMn"
217 " KLhaOykbhKSgxOmMxMjg6MVlKj2bjb7qFQVkLO1OPg28jSrtRpnQCR+qegN4ZmNam/qbest"
218 " 8yn0JQ6gxX7PvP382+jx7uHHWHYYqPq/Flf8gqtOOcjqS5TJgVHz3F3xHWquo1ZofGtCMro"
219 " Dd2c0xjRjIVGvLV6Ngs+HRdljRav40vRpTyEoEdlzHBQiILesopKSk=}";
220
221 struct rsa_ctx *ctx;
222 struct sexp_iterator i;
223
224 int res;
225
226 ctx = xalloc(sizeof(*ctx));
227
228 rsa_public_key_init (&ctx->pub);
229 rsa_private_key_init (&ctx->key);
230 mpz_init (ctx->s);
231 knuth_lfib_init (&ctx->lfib, 1);
232
233 /* NOTE: Base64-decodes the strings in-place */
234 if (size == 1024)
235 res = sexp_transport_iterator_first (&i, sizeof(rsa1024) - 1, rsa1024);
236 else if (size == 2048)
237 res = sexp_transport_iterator_first (&i, sizeof(rsa2048) - 1, rsa2048);
238 else
239 die ("Internal error.\n");
240
241 if (! (res
242 && sexp_iterator_check_type (&i, "private-key")
243 && sexp_iterator_check_type (&i, "rsa-pkcs1-sha1")
244 && rsa_keypair_from_sexp_alist (&ctx->pub, &ctx->key, 0, &i)))
245 die ("Internal error.\n");
246
247 ctx->digest = hash_string (&nettle_sha256, "foo");
248
249 rsa_sha256_sign_digest (&ctx->key, ctx->digest, ctx->s);
250
251 return ctx;
252 }
253
254 static void
bench_rsa_sign(void * p)255 bench_rsa_sign (void *p)
256 {
257 struct rsa_ctx *ctx = p;
258
259 mpz_t s;
260 mpz_init (s);
261 rsa_sha256_sign_digest (&ctx->key, ctx->digest, s);
262 mpz_clear (s);
263 }
264
265 static void
bench_rsa_sign_tr(void * p)266 bench_rsa_sign_tr (void *p)
267 {
268 struct rsa_ctx *ctx = p;
269
270 mpz_t s;
271 mpz_init (s);
272 rsa_sha256_sign_digest_tr (&ctx->pub, &ctx->key,
273 &ctx->lfib, (nettle_random_func *)knuth_lfib_random,
274 ctx->digest, s);
275 mpz_clear (s);
276 }
277
278 static void
bench_rsa_verify(void * p)279 bench_rsa_verify (void *p)
280 {
281 struct rsa_ctx *ctx = p;
282 if (! rsa_sha256_verify_digest (&ctx->pub, ctx->digest, ctx->s))
283 die ("Internal error, rsa_sha256_verify_digest failed.\n");
284 }
285
286 static void
bench_rsa_clear(void * p)287 bench_rsa_clear (void *p)
288 {
289 struct rsa_ctx *ctx = p;
290
291 rsa_public_key_clear (&ctx->pub);
292 rsa_private_key_clear (&ctx->key);
293 mpz_clear (ctx->s);
294
295 free (ctx->digest);
296 free (ctx);
297 }
298
299 struct dsa_ctx
300 {
301 struct dsa_params params;
302 mpz_t pub;
303 mpz_t key;
304 struct knuth_lfib_ctx lfib;
305 struct dsa_signature s;
306 uint8_t *digest;
307 };
308
309 static void *
bench_dsa_init(unsigned size)310 bench_dsa_init (unsigned size)
311 {
312 struct dsa_ctx *ctx;
313 struct sexp_iterator i;
314
315 unsigned char dsa1024[] =
316 "{KDExOnByaXZhdGUta2V5KDM6ZHNhKDE6cDEyOToA2q4hOXEClLMXXMOl9xaPcGC/GeGmCMv"
317 " VCaaW0uWc50DvvmJDPQPdCehyfZr/1dv2UDbx06TC7ls/IFd+BsDzGBRxqIQ44J20cn+0gt"
318 " NMIXAocE1QhCCFaT5gXrk8zMlqBEGaP3RdpgxNanEXkTj2Wma8r1GtrLX3HPafio62jicpK"
319 " DE6cTIxOgDN9pcW3exdVAesC9WsxwCGoJK24ykoMTpnMTI5OgCJr9DmKdiE0WJZB7HACESv"
320 " Tpg1qZgc8E15byQ+OsHUyOTRrJRTcrgKZJW7dFRJ9cXmyi7XYCd3bJtu/2HRHLY1vd4qMvU"
321 " 7Y8x08ooCoABGV7nGqcmdQfEho1OY6TZh2NikmPKZLeur3PZFpcZ8Dl+KVWtwC55plNC7Om"
322 " iAQy8MaCkoMTp5MTI5OgDakk0LOUQwzOKt9FHOBmBKrWsvTm7549eScTUqH4OMm3btjUsXz"
323 " MmlqEe+imwQCOW/AE3Xw9pXZeETWK0jlLe8k5vnKcNskerFwZ1eQKtOPPQty8IqQ9PEfF6B"
324 " 0oVQiJg2maHUDWFnDkIBd7ZR1z8FnZMUxH9mH4kEUo6YQgtCdykoMTp4MjA6cOl3ijiiMjI"
325 " pesFD8jxESWb2mn8pKSk=}";
326
327 ctx = xalloc(sizeof(*ctx));
328
329 dsa_params_init (&ctx->params);
330 mpz_init (ctx->pub);
331 mpz_init (ctx->key);
332 dsa_signature_init (&ctx->s);
333 knuth_lfib_init (&ctx->lfib, 1);
334
335 if (size != 1024)
336 die ("Internal error.\n");
337
338 if (! (sexp_transport_iterator_first (&i, sizeof(dsa1024) - 1, dsa1024)
339 && sexp_iterator_check_type (&i, "private-key")
340 && sexp_iterator_check_type (&i, "dsa")
341 && dsa_keypair_from_sexp_alist (&ctx->params, ctx->pub, ctx->key,
342 0, DSA_SHA1_Q_BITS, &i)) )
343 die ("Internal error.\n");
344
345 ctx->digest = hash_string (&nettle_sha1, "foo");
346
347 dsa_sign (&ctx->params, ctx->key,
348 &ctx->lfib, (nettle_random_func *)knuth_lfib_random,
349 SHA1_DIGEST_SIZE, ctx->digest, &ctx->s);
350
351 return ctx;
352 }
353
354 static void
bench_dsa_sign(void * p)355 bench_dsa_sign (void *p)
356 {
357 struct dsa_ctx *ctx = p;
358 struct dsa_signature s;
359
360 dsa_signature_init (&s);
361 dsa_sign (&ctx->params, ctx->key,
362 &ctx->lfib, (nettle_random_func *)knuth_lfib_random,
363 SHA1_DIGEST_SIZE, ctx->digest, &s);
364 dsa_signature_clear (&s);
365 }
366
367 static void
bench_dsa_verify(void * p)368 bench_dsa_verify (void *p)
369 {
370 struct dsa_ctx *ctx = p;
371 if (! dsa_verify (&ctx->params, ctx->pub, SHA1_DIGEST_SIZE, ctx->digest, &ctx->s))
372 die ("Internal error, dsa_sha1_verify_digest failed.\n");
373 }
374
375 static void
bench_dsa_clear(void * p)376 bench_dsa_clear (void *p)
377 {
378 struct dsa_ctx *ctx = p;
379 dsa_params_clear (&ctx->params);
380 mpz_clear (ctx->pub);
381 mpz_clear (ctx->key);
382 dsa_signature_clear (&ctx->s);
383 free (ctx->digest);
384 free (ctx);
385 }
386
387 struct ecdsa_ctx
388 {
389 struct ecc_point pub;
390 struct ecc_scalar key;
391 struct knuth_lfib_ctx lfib;
392 unsigned digest_size;
393 uint8_t *digest;
394 struct dsa_signature s;
395 };
396
397 static void *
bench_ecdsa_init(unsigned size)398 bench_ecdsa_init (unsigned size)
399 {
400 struct ecdsa_ctx *ctx;
401 const struct ecc_curve *ecc;
402
403 const char *xs;
404 const char *ys;
405 const char *zs;
406 mpz_t x, y, z;
407
408 ctx = xalloc (sizeof(*ctx));
409
410 dsa_signature_init (&ctx->s);
411 knuth_lfib_init (&ctx->lfib, 17);
412
413 switch (size)
414 {
415 case 192:
416 ecc = &_nettle_secp_192r1;
417 xs = "8e8e07360350fb6b7ad8370cfd32fa8c6bba785e6e200599";
418 ys = "7f82ddb58a43d59ff8dc66053002b918b99bd01bd68d6736";
419 zs = "f2e620e086d658b4b507996988480917640e4dc107808bdd";
420 ctx->digest = hash_string (&nettle_sha1, "abc");
421 ctx->digest_size = 20;
422 break;
423 case 224:
424 ecc = &_nettle_secp_224r1;
425 xs = "993bf363f4f2bc0f255f22563980449164e9c894d9efd088d7b77334";
426 ys = "b75fff9849997d02d135140e4d0030944589586e22df1fc4b629082a";
427 zs = "cdfd01838247f5de3cc70b688418046f10a2bfaca6de9ec836d48c27";
428 ctx->digest = hash_string (&nettle_sha224, "abc");
429 ctx->digest_size = 28;
430 break;
431
432 /* From RFC 4754 */
433 case 256:
434 ecc = &_nettle_secp_256r1;
435 xs = "2442A5CC 0ECD015F A3CA31DC 8E2BBC70 BF42D60C BCA20085 E0822CB0 4235E970";
436 ys = "6FC98BD7 E50211A4 A27102FA 3549DF79 EBCB4BF2 46B80945 CDDFE7D5 09BBFD7D";
437 zs = "DC51D386 6A15BACD E33D96F9 92FCA99D A7E6EF09 34E70975 59C27F16 14C88A7F";
438 ctx->digest = hash_string (&nettle_sha256, "abc");
439 ctx->digest_size = 32;
440 break;
441 case 384:
442 ecc = &_nettle_secp_384r1;
443 xs = "96281BF8 DD5E0525 CA049C04 8D345D30 82968D10 FEDF5C5A CA0C64E6 465A97EA"
444 "5CE10C9D FEC21797 41571072 1F437922";
445 ys = "447688BA 94708EB6 E2E4D59F 6AB6D7ED FF9301D2 49FE49C3 3096655F 5D502FAD"
446 "3D383B91 C5E7EDAA 2B714CC9 9D5743CA";
447 zs = "0BEB6466 34BA8773 5D77AE48 09A0EBEA 865535DE 4C1E1DCB 692E8470 8E81A5AF"
448 "62E528C3 8B2A81B3 5309668D 73524D9F";
449 ctx->digest = hash_string (&nettle_sha384, "abc");
450 ctx->digest_size = 48;
451 break;
452 case 521:
453 ecc = &_nettle_secp_521r1;
454 xs = "0151518F 1AF0F563 517EDD54 85190DF9 5A4BF57B 5CBA4CF2 A9A3F647 4725A35F"
455 "7AFE0A6D DEB8BEDB CD6A197E 592D4018 8901CECD 650699C9 B5E456AE A5ADD190"
456 "52A8";
457 ys = "006F3B14 2EA1BFFF 7E2837AD 44C9E4FF 6D2D34C7 3184BBAD 90026DD5 E6E85317"
458 "D9DF45CA D7803C6C 20035B2F 3FF63AFF 4E1BA64D 1C077577 DA3F4286 C58F0AEA"
459 "E643";
460 zs = "0065FDA3 409451DC AB0A0EAD 45495112 A3D813C1 7BFD34BD F8C1209D 7DF58491"
461 "20597779 060A7FF9 D704ADF7 8B570FFA D6F062E9 5C7E0C5D 5481C5B1 53B48B37"
462 "5FA1";
463
464 ctx->digest = hash_string (&nettle_sha512, "abc");
465 ctx->digest_size = 64;
466 break;
467 default:
468 die ("Internal error.\n");
469 }
470 ecc_point_init (&ctx->pub, ecc);
471 ecc_scalar_init (&ctx->key, ecc);
472
473 mpz_init_set_str (x, xs, 16);
474 mpz_init_set_str (y, ys, 16);
475 mpz_init_set_str (z, zs, 16);
476
477 ecc_point_set (&ctx->pub, x, y);
478 ecc_scalar_set (&ctx->key, z);
479
480 mpz_clear (x);
481 mpz_clear (y);
482 mpz_clear (z);
483
484 ecdsa_sign (&ctx->key,
485 &ctx->lfib, (nettle_random_func *) knuth_lfib_random,
486 ctx->digest_size, ctx->digest,
487 &ctx->s);
488
489 return ctx;
490 }
491
492 static void
bench_ecdsa_sign(void * p)493 bench_ecdsa_sign (void *p)
494 {
495 struct ecdsa_ctx *ctx = p;
496 struct dsa_signature s;
497
498 dsa_signature_init (&s);
499 ecdsa_sign (&ctx->key,
500 &ctx->lfib, (nettle_random_func *) knuth_lfib_random,
501 ctx->digest_size, ctx->digest,
502 &s);
503 dsa_signature_clear (&s);
504 }
505
506 static void
bench_ecdsa_verify(void * p)507 bench_ecdsa_verify (void *p)
508 {
509 struct ecdsa_ctx *ctx = p;
510 if (! ecdsa_verify (&ctx->pub,
511 ctx->digest_size, ctx->digest,
512 &ctx->s))
513 die ("Internal error, ecdsa_verify failed.\n");
514 }
515
516 static void
bench_ecdsa_clear(void * p)517 bench_ecdsa_clear (void *p)
518 {
519 struct ecdsa_ctx *ctx = p;
520
521 ecc_point_clear (&ctx->pub);
522 ecc_scalar_clear (&ctx->key);
523 dsa_signature_clear (&ctx->s);
524 free (ctx->digest);
525
526 free (ctx);
527 }
528
529 struct eddsa_ctx
530 {
531 uint8_t pub[ED448_KEY_SIZE];
532 uint8_t key[ED448_KEY_SIZE];
533 uint8_t signature[ED448_SIGNATURE_SIZE];
534 void (*sign)(const uint8_t *pub,
535 const uint8_t *priv,
536 size_t length, const uint8_t *msg,
537 uint8_t *signature);
538 int (*verify)(const uint8_t *pub,
539 size_t length, const uint8_t *msg,
540 const uint8_t *signature);
541 };
542
543 static void *
bench_eddsa_init(unsigned size)544 bench_eddsa_init (unsigned size)
545 {
546 struct knuth_lfib_ctx lfib;
547 struct eddsa_ctx *ctx;
548 knuth_lfib_init (&lfib, 17);
549
550 ctx = xalloc (sizeof(*ctx));
551 switch (size) {
552 case 255:
553 ctx->sign = ed25519_sha512_sign;
554 ctx->verify = ed25519_sha512_verify;
555
556 knuth_lfib_random (&lfib, ED25519_KEY_SIZE, ctx->key);
557 ed25519_sha512_public_key (ctx->pub, ctx->key);
558 break;
559 case 448:
560 ctx->sign = ed448_shake256_sign;
561 ctx->verify = ed448_shake256_verify;
562
563 knuth_lfib_random (&lfib, ED448_KEY_SIZE, ctx->key);
564 ed448_shake256_public_key (ctx->pub, ctx->key);
565 break;
566 default:
567 abort ();
568 }
569 ctx->sign (ctx->pub, ctx->key, 3, (const uint8_t *) "abc", ctx->signature);
570
571 return ctx;
572 }
573
574 static void
bench_eddsa_sign(void * p)575 bench_eddsa_sign (void *p)
576 {
577 struct eddsa_ctx *ctx = p;
578 ctx->sign (ctx->pub, ctx->key, 3, (const uint8_t *) "abc", ctx->signature);
579 }
580
581 static void
bench_eddsa_verify(void * p)582 bench_eddsa_verify (void *p)
583 {
584 struct eddsa_ctx *ctx = p;
585 if (!ctx->verify (ctx->pub, 3, (const uint8_t *) "abc", ctx->signature))
586 die ("Internal error, eddsa_verify failed.\n");
587 }
588
589 static void
bench_eddsa_clear(void * p)590 bench_eddsa_clear (void *p)
591 {
592 free (p);
593 }
594
595 static void *
bench_gostdsa_init(unsigned size)596 bench_gostdsa_init (unsigned size)
597 {
598 struct ecdsa_ctx *ctx;
599 const struct ecc_curve *ecc;
600
601 const char *xs;
602 const char *ys;
603 const char *zs;
604 mpz_t x, y, z;
605
606 ctx = xalloc (sizeof(*ctx));
607
608 dsa_signature_init (&ctx->s);
609 knuth_lfib_init (&ctx->lfib, 17);
610
611 switch (size)
612 {
613 case 256:
614 ecc = &_nettle_gost_gc256b;
615 xs = "971566ceda436ee7678f7e07e84ebb7217406c0b4747aa8fd2ab1453c3d0dfba";
616 ys = "ad58736965949f8e59830f8de20fc6c0d177f6ab599874f1e2e24ff71f9ce643";
617 zs = "bfcf1d623e5cdd3032a7c6eabb4a923c46e43d640ffeaaf2c3ed39a8fa399924";
618 ctx->digest = hash_string (&nettle_sha256, "abc");
619 ctx->digest_size = 32;
620 break;
621
622 case 512:
623 ecc = &_nettle_gost_gc512a;
624 xs = "03A36340A95BB5F93D131961B5B1C1B3213DF7FF3B5A30376407E2A65C441BC6"
625 "D1B34662317083243F007B15A8512B526606D3B172B606DCE86DBD6F82DA3D40";
626 ys = "DEAD76318012FED79507809C89CC44848743640EAC9A3C847DA9082E050760A1"
627 "0679F4B707ABC1872640AD20D7441F66C7A8B3BFF1B8E11B4A076F0A86749F73";
628 zs = "3FC01CDCD4EC5F972EB482774C41E66DB7F380528DFE9E67992BA05AEE462435"
629 "757530E641077CE587B976C8EEB48C48FD33FD175F0C7DE6A44E014E6BCB074B";
630 ctx->digest = hash_string (&nettle_sha512, "abc");
631 ctx->digest_size = 64;
632 break;
633
634 default:
635 die ("Internal error.\n");
636 }
637 ecc_point_init (&ctx->pub, ecc);
638 ecc_scalar_init (&ctx->key, ecc);
639
640 mpz_init_set_str (x, xs, 16);
641 mpz_init_set_str (y, ys, 16);
642 mpz_init_set_str (z, zs, 16);
643
644 ecc_point_set (&ctx->pub, x, y);
645 ecc_scalar_set (&ctx->key, z);
646
647 mpz_clear (x);
648 mpz_clear (y);
649 mpz_clear (z);
650
651 gostdsa_sign (&ctx->key,
652 &ctx->lfib, (nettle_random_func *) knuth_lfib_random,
653 ctx->digest_size, ctx->digest,
654 &ctx->s);
655
656 return ctx;
657 }
658
659 static void
bench_gostdsa_sign(void * p)660 bench_gostdsa_sign (void *p)
661 {
662 struct ecdsa_ctx *ctx = p;
663 struct dsa_signature s;
664
665 dsa_signature_init (&s);
666 gostdsa_sign (&ctx->key,
667 &ctx->lfib, (nettle_random_func *) knuth_lfib_random,
668 ctx->digest_size, ctx->digest,
669 &s);
670 dsa_signature_clear (&s);
671 }
672
673 static void
bench_gostdsa_verify(void * p)674 bench_gostdsa_verify (void *p)
675 {
676 struct ecdsa_ctx *ctx = p;
677 if (! gostdsa_verify (&ctx->pub,
678 ctx->digest_size, ctx->digest,
679 &ctx->s))
680 die ("Internal error, _gostdsa_verify failed.\n");
681 }
682
683 static void
bench_gostdsa_clear(void * p)684 bench_gostdsa_clear (void *p)
685 {
686 struct ecdsa_ctx *ctx = p;
687
688 ecc_point_clear (&ctx->pub);
689 ecc_scalar_clear (&ctx->key);
690 dsa_signature_clear (&ctx->s);
691 free (ctx->digest);
692
693 free (ctx);
694 }
695
696 #if WITH_OPENSSL
697 struct openssl_rsa_ctx
698 {
699 RSA *key;
700 unsigned char *ref;
701 unsigned char *signature;
702 unsigned int siglen;
703 uint8_t *digest;
704 };
705
706 static struct openssl_rsa_ctx*
make_openssl_rsa_ctx(unsigned size)707 make_openssl_rsa_ctx (unsigned size)
708 {
709 struct openssl_rsa_ctx *ctx = xalloc (sizeof (*ctx));
710 BIGNUM *e = BN_new();
711 BN_set_word(e, 65537);
712 ctx->key = RSA_new();
713 RSA_generate_key_ex (ctx->key, size, e, NULL);
714 ctx->ref = xalloc (RSA_size (ctx->key));
715 ctx->signature = xalloc (RSA_size (ctx->key));
716 ctx->digest = hash_string (&nettle_sha1, "foo");
717
718 if (! RSA_sign (NID_sha1, ctx->digest, SHA1_DIGEST_SIZE,
719 ctx->ref, &ctx->siglen, ctx->key))
720 die ("OpenSSL RSA_sign failed.\n");
721
722 BN_free(e);
723 return ctx;
724 }
725
726 static void *
bench_openssl_rsa_init(unsigned size)727 bench_openssl_rsa_init (unsigned size)
728 {
729 struct openssl_rsa_ctx *ctx = make_openssl_rsa_ctx (size);
730 RSA_blinding_off(ctx->key);
731 return ctx;
732 }
733
734 static void *
bench_openssl_rsa_tr_init(unsigned size)735 bench_openssl_rsa_tr_init (unsigned size)
736 {
737 return make_openssl_rsa_ctx (size);
738 }
739
740 static void
bench_openssl_rsa_sign(void * p)741 bench_openssl_rsa_sign (void *p)
742 {
743 const struct openssl_rsa_ctx *ctx = p;
744 unsigned siglen;
745
746 if (! RSA_sign (NID_sha1, ctx->digest, SHA1_DIGEST_SIZE,
747 ctx->signature, &siglen, ctx->key))
748 die ("OpenSSL RSA_sign failed.\n");
749 }
750
751 static void
bench_openssl_rsa_verify(void * p)752 bench_openssl_rsa_verify (void *p)
753 {
754 const struct openssl_rsa_ctx *ctx = p;
755 if (! RSA_verify (NID_sha1, ctx->digest, SHA1_DIGEST_SIZE,
756 ctx->ref, ctx->siglen, ctx->key))
757 die ("OpenSSL RSA_verify failed.\n");
758 }
759
760 static void
bench_openssl_rsa_clear(void * p)761 bench_openssl_rsa_clear (void *p)
762 {
763 struct openssl_rsa_ctx *ctx = p;
764 RSA_free (ctx->key);
765 free (ctx->ref);
766 free (ctx->signature);
767 free (ctx->digest);
768 free (ctx);
769 }
770
771 struct openssl_ecdsa_ctx
772 {
773 EC_KEY *key;
774 ECDSA_SIG *signature;
775 unsigned digest_length;
776 uint8_t *digest;
777 };
778
779 static void *
bench_openssl_ecdsa_init(unsigned size)780 bench_openssl_ecdsa_init (unsigned size)
781 {
782 struct openssl_ecdsa_ctx *ctx = xalloc (sizeof (*ctx));
783
784 switch (size)
785 {
786 case 192:
787 ctx->key = EC_KEY_new_by_curve_name (NID_X9_62_prime192v1);
788 ctx->digest_length = 24; /* truncated */
789 ctx->digest = hash_string (&nettle_sha224, "abc");
790 break;
791 case 224:
792 ctx->key = EC_KEY_new_by_curve_name (NID_secp224r1);
793 ctx->digest_length = SHA224_DIGEST_SIZE;
794 ctx->digest = hash_string (&nettle_sha224, "abc");
795 break;
796 case 256:
797 ctx->key = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
798 ctx->digest_length = SHA256_DIGEST_SIZE;
799 ctx->digest = hash_string (&nettle_sha256, "abc");
800 break;
801 case 384:
802 ctx->key = EC_KEY_new_by_curve_name (NID_secp384r1);
803 ctx->digest_length = SHA384_DIGEST_SIZE;
804 ctx->digest = hash_string (&nettle_sha384, "abc");
805 break;
806 case 521:
807 ctx->key = EC_KEY_new_by_curve_name (NID_secp521r1);
808 ctx->digest_length = SHA512_DIGEST_SIZE;
809 ctx->digest = hash_string (&nettle_sha512, "abc");
810 break;
811 default:
812 die ("Internal error.\n");
813 }
814
815 /* This curve isn't supported in this build of openssl */
816 if (ctx->key == NULL)
817 {
818 free(ctx);
819 return NULL;
820 }
821
822 if (!EC_KEY_generate_key( ctx->key))
823 die ("Openssl EC_KEY_generate_key failed.\n");
824
825 ctx->signature = ECDSA_do_sign (ctx->digest, ctx->digest_length, ctx->key);
826
827 return ctx;
828 }
829
830 static void
bench_openssl_ecdsa_sign(void * p)831 bench_openssl_ecdsa_sign (void *p)
832 {
833 const struct openssl_ecdsa_ctx *ctx = p;
834 ECDSA_SIG *sig = ECDSA_do_sign (ctx->digest, ctx->digest_length, ctx->key);
835 ECDSA_SIG_free (sig);
836 }
837
838 static void
bench_openssl_ecdsa_verify(void * p)839 bench_openssl_ecdsa_verify (void *p)
840 {
841 const struct openssl_ecdsa_ctx *ctx = p;
842 if (ECDSA_do_verify (ctx->digest, ctx->digest_length,
843 ctx->signature, ctx->key) != 1)
844 die ("Openssl ECDSA_do_verify failed.\n");
845 }
846 static void
bench_openssl_ecdsa_clear(void * p)847 bench_openssl_ecdsa_clear (void *p)
848 {
849 struct openssl_ecdsa_ctx *ctx = p;
850 ECDSA_SIG_free (ctx->signature);
851 EC_KEY_free (ctx->key);
852 free (ctx->digest);
853 free (ctx);
854 }
855 #endif
856
857 struct curve_ctx
858 {
859 uint8_t x[CURVE448_SIZE];
860 uint8_t s[CURVE448_SIZE];
861 void (*mul_g)(uint8_t *q, const uint8_t *n);
862 void (*mul)(uint8_t *q, const uint8_t *n, const uint8_t *p);
863 };
864
865 static void *
bench_curve_init(unsigned size)866 bench_curve_init (unsigned size)
867 {
868 struct knuth_lfib_ctx lfib;
869 struct curve_ctx *ctx = xalloc (sizeof (*ctx));
870 knuth_lfib_init (&lfib, 17);
871 switch (size)
872 {
873 case 255:
874 ctx->mul = curve25519_mul;
875 ctx->mul_g = curve25519_mul_g;
876 knuth_lfib_random (&lfib, CURVE25519_SIZE, ctx->s);
877 break;
878 case 448:
879 ctx->mul = curve448_mul;
880 ctx->mul_g = curve448_mul_g;
881 knuth_lfib_random (&lfib, CURVE448_SIZE, ctx->s);
882 break;
883 default:
884 abort ();
885 }
886 ctx->mul_g (ctx->x, ctx->s);
887 return ctx;
888 }
889
890 static void
bench_curve_mul_g(void * p)891 bench_curve_mul_g (void *p)
892 {
893 struct curve_ctx *ctx = p;
894 uint8_t q[CURVE448_SIZE];
895 ctx->mul_g (q, ctx->s);
896 }
897
898 static void
bench_curve_mul(void * p)899 bench_curve_mul (void *p)
900 {
901 struct curve_ctx *ctx = p;
902 uint8_t q[CURVE448_SIZE];
903 ctx->mul (q, ctx->s, ctx->x);
904 }
905
906 static void
bench_curve_clear(void * p)907 bench_curve_clear (void *p)
908 {
909 free (p);
910 }
911
912 struct alg alg_list[] = {
913 { "rsa", 1024, bench_rsa_init, bench_rsa_sign, bench_rsa_verify, bench_rsa_clear },
914 { "rsa", 2048, bench_rsa_init, bench_rsa_sign, bench_rsa_verify, bench_rsa_clear },
915 { "rsa-tr", 1024, bench_rsa_init, bench_rsa_sign_tr, bench_rsa_verify, bench_rsa_clear },
916 { "rsa-tr", 2048, bench_rsa_init, bench_rsa_sign_tr, bench_rsa_verify, bench_rsa_clear },
917 #if WITH_OPENSSL
918 { "rsa (openssl)", 1024, bench_openssl_rsa_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
919 { "rsa (openssl)", 2048, bench_openssl_rsa_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
920 { "rsa-tr (openssl)", 1024, bench_openssl_rsa_tr_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
921 { "rsa-tr (openssl)", 2048, bench_openssl_rsa_tr_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
922 #endif
923 { "dsa", 1024, bench_dsa_init, bench_dsa_sign, bench_dsa_verify, bench_dsa_clear },
924 #if 0
925 { "dsa",2048, bench_dsa_init, bench_dsa_sign, bench_dsa_verify, bench_dsa_clear },
926 #endif
927 { "ecdsa", 192, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
928 { "ecdsa", 224, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
929 { "ecdsa", 256, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
930 { "ecdsa", 384, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
931 { "ecdsa", 521, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
932 #if WITH_OPENSSL
933 { "ecdsa (openssl)", 192, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
934 { "ecdsa (openssl)", 224, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
935 { "ecdsa (openssl)", 256, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
936 { "ecdsa (openssl)", 384, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
937 { "ecdsa (openssl)", 521, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
938 #endif
939 { "eddsa", 255, bench_eddsa_init, bench_eddsa_sign, bench_eddsa_verify, bench_eddsa_clear },
940 { "eddsa", 448, bench_eddsa_init, bench_eddsa_sign, bench_eddsa_verify, bench_eddsa_clear },
941 { "curve", 255, bench_curve_init, bench_curve_mul_g, bench_curve_mul, bench_curve_clear},
942 { "curve", 448, bench_curve_init, bench_curve_mul_g, bench_curve_mul, bench_curve_clear },
943 { "gostdsa", 256, bench_gostdsa_init, bench_gostdsa_sign, bench_gostdsa_verify, bench_gostdsa_clear },
944 { "gostdsa", 512, bench_gostdsa_init, bench_gostdsa_sign, bench_gostdsa_verify, bench_gostdsa_clear },
945 };
946
947 #define numberof(x) (sizeof (x) / sizeof ((x)[0]))
948
949 int
main(int argc,char ** argv)950 main (int argc, char **argv)
951 {
952 const char *filter = NULL;
953 unsigned i;
954
955 if (argc > 1)
956 filter = argv[1];
957
958 time_init();
959 printf ("%16s %4s %9s %9s\n",
960 "name", "size", "sign/ms", "verify/ms");
961
962 for (i = 0; i < numberof(alg_list); i++)
963 if (!filter || strstr (alg_list[i].name, filter))
964 bench_alg (&alg_list[i]);
965
966 return EXIT_SUCCESS;
967 }
968