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