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 "curve25519.h"
51 
52 #include "nettle-meta.h"
53 #include "sexp.h"
54 #include "knuth-lfib.h"
55 
56 #include "../ecdsa.h"
57 #include "../ecc-internal.h"
58 #include "../gmp-glue.h"
59 
60 #if WITH_OPENSSL
61 #include <openssl/rsa.h>
62 #include <openssl/bn.h>
63 #include <openssl/ec.h>
64 #include <openssl/ecdsa.h>
65 #include <openssl/objects.h>
66 #endif
67 
68 #define BENCH_INTERVAL 0.1
69 
70 static void NORETURN PRINTF_STYLE(1,2)
die(const char * format,...)71 die(const char *format, ...)
72 {
73   va_list args;
74   va_start(args, format);
75   vfprintf(stderr, format, args);
76   va_end(args);
77 
78   exit(EXIT_FAILURE);
79 }
80 
81 static void *
xalloc(size_t size)82 xalloc (size_t size)
83 {
84   void *p = malloc (size);
85   if (!p)
86     {
87       fprintf (stderr, "Virtual memory exhausted\n");
88       abort ();
89     }
90   return p;
91 }
92 
93 static uint8_t *
hash_string(const struct nettle_hash * hash,const char * s)94 hash_string (const struct nettle_hash *hash, const char *s)
95 {
96   void *ctx = xalloc (hash->context_size);
97   uint8_t *digest = xalloc (hash->digest_size);
98   hash->init (ctx);
99   hash->update (ctx, strlen(s), (const uint8_t *) s);
100   hash->digest (ctx, hash->digest_size, digest);
101   free (ctx);
102 
103   return digest;
104 }
105 
106 struct alg {
107   const char *name;
108   unsigned size;
109   void *(*init) (unsigned size);
110   void (*sign)  (void *);
111   void (*verify)(void *);
112   void (*clear) (void *);
113 };
114 
115 /* Returns second per function call */
116 static double
time_function(void (* f)(void * arg),void * arg)117 time_function(void (*f)(void *arg), void *arg)
118 {
119   unsigned ncalls;
120   double elapsed;
121 
122   /* Warm up */
123   f(arg);
124   for (ncalls = 10 ;;)
125     {
126       unsigned i;
127 
128       time_start();
129       for (i = 0; i < ncalls; i++)
130 	f(arg);
131       elapsed = time_end();
132       if (elapsed > BENCH_INTERVAL)
133 	break;
134       else if (elapsed < BENCH_INTERVAL / 10)
135 	ncalls *= 10;
136       else
137 	ncalls *= 2;
138     }
139   return elapsed / ncalls;
140 }
141 
142 static void
bench_alg(const struct alg * alg)143 bench_alg (const struct alg *alg)
144 {
145   double sign;
146   double verify;
147   void *ctx;
148 
149   ctx = alg->init(alg->size);
150   if (ctx == NULL)
151     {
152       printf("%16s %4d N/A\n", alg->name, alg->size);
153       return;
154     }
155 
156   sign = time_function (alg->sign, ctx);
157   verify = time_function (alg->verify, ctx);
158 
159   alg->clear (ctx);
160 
161   printf("%16s %4d %9.4f %9.4f\n",
162 	 alg->name, alg->size, 1e-3/sign, 1e-3/verify);
163 }
164 
165 struct rsa_ctx
166 {
167   struct rsa_public_key pub;
168   struct rsa_private_key key;
169   struct knuth_lfib_ctx lfib;
170   uint8_t *digest;
171   mpz_t s;
172 };
173 
174 static void *
bench_rsa_init(unsigned size)175 bench_rsa_init (unsigned size)
176 {
177   unsigned char rsa1024[] =
178     "{KDExOnByaXZhdGUta2V5KDE0OnJzYS1wa2NzMS1zaGExKDE6bjEyOToA90+K5EmjbFJBeJD"
179     " xP2KD2Df+0Twc9425uB+vhqTrVijtd2PnwEQDfR2VoducgkKcXJzYYyCNILQJbFAi2Km/sD"
180     " jImERBqDtaI217Ze+tOKEmImexYTAgFuqEptp2F3M4DqgRQ7s/3nJQ/bPE5Hfi1OZhJSShu"
181     " I80ATTU4fUgrPspKDE6ZTM6AQABKSgxOmQxMjk6APAhKckzvxxkWfHJOpXDACWnaSKcbbvo"
182     " vtWK3pGr/F2ya7CrLtE+uOx5F1sLs9G+/7flCy5k4uNILIYg4VTirZ1zQ8fNKPrjK1VMRls"
183     " JiRRU/0VAs9d7HdncJfs6rbvRQbCRSRYURo4hWir3Lq8V3UUQVBprc4dO+uWmplvwQ5qxKS"
184     " gxOnA2NToA+8aIVkdbk8Jg8dJOuzc7m/hZnwkKSs6eVDw4N/2T0CJKGJYT+B3Ct+fPkxhUR"
185     " ggd2DQ9OpkTra7SXHTNkzdPVSkoMTpxNjU6APt11P8vXNnGYF0OC/cPsR8zhSYuFmtRuX6G"
186     " ES+DdG0VCU07UeNQkok1UoW5sXqY0IGr1jkJq8AMSgKoNbLQ6w8pKDE6YTY0Ohzkxsan/8F"
187     " wQDHgQbrIduXKVXaj0fONzKu8EXOTfUAYf0pdBsOlnq/+QVsPIrS6v7oNHK253YFEG84SdX"
188     " kcktUpKDE6YjY1OgCR+cRtY3RWY+f6/TWK9gwPndv03xpasLWrMm71ky1aSbT9pasS9+opR"
189     " tAiGzthfSbFsBiLQgb3VOr+AeIybT+XKSgxOmM2NDojigqARWN5u1CVDVuD2L2ManpoGiM6"
190     " kQ6FaJjqRjxeRRKFrQxGJa9tM1hqStxokC1oJidgaOLGnn60iwzToug9KSkp}";
191 
192   unsigned char rsa2048[] =
193     "{KDExOnByaXZhdGUta2V5KDE0OnJzYS1wa2NzMS1zaGExKDE6bjI1NzoAtxWXiglIdunDK48"
194     " 8I0vW0wTqnh/riW9pLk8n1F8MUPBFdhvkkl0bDQqSJPUvSHy+w4fLVwcEzeI4qFyo3b2Avz"
195     " JK20MFbt/WfHD1TbxuK8rNqXyqmqjJ9vgjtV9nPzAz7CM9ogs3/RJHpcfZPQF15ifizleUZ"
196     " aQT0GAXHZL7cePj10yGI2u3hgTkokVzdNC/1T34guKYpErg0pt0B/KejWpsFTb84z3tkR+B"
197     " YVx07p/OoByZwoABgncS/uALl31fRS8jyJ2JqUiZOqe7XoO9hkDHYNCWUGUfNGQ7ZgVp9+e"
198     " NQpracSjrp6Jnrj7r/oxJUx5ZDVNi18AzQadE/oKOrSkoMTplMzoBAAEpKDE6ZDI1NjogBT"
199     " C5vaHk2kF+LtDvw2XRBj0aZq7FHK0ioklvBSicR0l+vKYfSxVeFIk22YLphJfAjtFraRjYA"
200     " Uaze3E1Rt1rkxoweupKV++lWAQvElOaaR/LErirz/Vysjdck1D1ZjLOi+NNofSq2DWbsvY1"
201     " iznZhQRP3lVf6XBls0iXrYs4gb0pBZqXLQW+j9Ihx6eantf1/6ZMKPgCkzcAZ0ABsCfaFSg"
202     " ouNCzilblsgFEspEbb8QqrNQoStS3F/gMwWgDsr3+vQzBqt+7ykWoCJ9wctbYy9kEPq+hX3"
203     " GP0hG6HdS81r9E8pgdf3wloNNMzYUHwn7poXGpOi8tG0pmR56TqD/BKSgxOnAxMjk6AN4AJ"
204     " TiGPm9We2ga3Y0jpTfA3mWpUbhYgaXYLWA1/riniwq16fqxRIkWQT/O2KKpBVe6WSvNYq9u"
205     " lM8N6bdPtDytJs6AOXy0X5vtJ953ZYVMhHbhmUxhIL9I+s0O1+LxMF8b9U4CrFyaTxd8Un/"
206     " FXP1BvYJRrkoup6HYvOlGx36lKSgxOnExMjk6ANMfrfH6z/3o7K56aW6kSiloDDbKZQ0+W5"
207     " 8LzP2ZOBLf6LX6jLhN3olU1Z0KGTM0S/1AxvwGjuRqhu+LcOJ7oUCUH3uusR5c5nSnArYPq"
208     " +0wbco4BQngot/HmGN7U0EDsIWqPt/qoa/b8bCk+TOwJlknNq/PnZU26SPj48XS05lpKSgx"
209     " OmExMjk6AJM2n3gLNW3ZeH5BindkktQU9qWNkV5geqDCaNyrEZ3bpI1WsrEGSj9p3Zz1ipz"
210     " a3msdbLJqQS26c72WKUzg8tFltR0s1HJInjolGtIgdNbfNdwrn9+RbQjL2VyPokOg0wXO4W"
211     " 14wlmqDhax33dRJmfe50964MvaglkGA8fhorrtKSgxOmIxMjk6AKMe+vrX2xRHf3dfxU5jS"
212     " ZmsdqNuxZzx7UB5kazvUU/kCJ1yNH/CSoq5LULkpovVgFDwV84qEwWQ+SjkCBg1hWWsDJc3"
213     " ZkobZUQENigM+72LiYiQt/PlyHI2eRuEEdNN0nm0DFhdpQeHXLoq/RBerYJ8tdgpBYxgnMn"
214     " KLhaOykbhKSgxOmMxMjg6MVlKj2bjb7qFQVkLO1OPg28jSrtRpnQCR+qegN4ZmNam/qbest"
215     " 8yn0JQ6gxX7PvP382+jx7uHHWHYYqPq/Flf8gqtOOcjqS5TJgVHz3F3xHWquo1ZofGtCMro"
216     " Dd2c0xjRjIVGvLV6Ngs+HRdljRav40vRpTyEoEdlzHBQiILesopKSk=}";
217 
218   struct rsa_ctx *ctx;
219   struct sexp_iterator i;
220 
221   int res;
222 
223   ctx = xalloc(sizeof(*ctx));
224 
225   rsa_public_key_init (&ctx->pub);
226   rsa_private_key_init (&ctx->key);
227   mpz_init (ctx->s);
228   knuth_lfib_init (&ctx->lfib, 1);
229 
230   /* NOTE: Base64-decodes the strings in-place */
231   if (size == 1024)
232     res = sexp_transport_iterator_first (&i, sizeof(rsa1024) - 1, rsa1024);
233   else if (size == 2048)
234     res = sexp_transport_iterator_first (&i, sizeof(rsa2048) - 1, rsa2048);
235   else
236     die ("Internal error.\n");
237 
238   if (! (res
239 	 && sexp_iterator_check_type (&i, "private-key")
240 	 && sexp_iterator_check_type (&i, "rsa-pkcs1-sha1")
241 	 && rsa_keypair_from_sexp_alist (&ctx->pub, &ctx->key, 0, &i)))
242     die ("Internal error.\n");
243 
244   ctx->digest = hash_string (&nettle_sha256, "foo");
245 
246   rsa_sha256_sign_digest (&ctx->key, ctx->digest, ctx->s);
247 
248   return ctx;
249 }
250 
251 static void
bench_rsa_sign(void * p)252 bench_rsa_sign (void *p)
253 {
254   struct rsa_ctx *ctx = p;
255 
256   mpz_t s;
257   mpz_init (s);
258   rsa_sha256_sign_digest (&ctx->key, ctx->digest, s);
259   mpz_clear (s);
260 }
261 
262 static void
bench_rsa_sign_tr(void * p)263 bench_rsa_sign_tr (void *p)
264 {
265   struct rsa_ctx *ctx = p;
266 
267   mpz_t s;
268   mpz_init (s);
269   rsa_sha256_sign_digest_tr (&ctx->pub, &ctx->key,
270 			     &ctx->lfib, (nettle_random_func *)knuth_lfib_random,
271 			     ctx->digest, s);
272   mpz_clear (s);
273 }
274 
275 static void
bench_rsa_verify(void * p)276 bench_rsa_verify (void *p)
277 {
278   struct rsa_ctx *ctx = p;
279   if (! rsa_sha256_verify_digest (&ctx->pub, ctx->digest, ctx->s))
280     die ("Internal error, rsa_sha256_verify_digest failed.\n");
281 }
282 
283 static void
bench_rsa_clear(void * p)284 bench_rsa_clear (void *p)
285 {
286   struct rsa_ctx *ctx = p;
287 
288   rsa_public_key_clear (&ctx->pub);
289   rsa_private_key_clear (&ctx->key);
290   mpz_clear (ctx->s);
291 
292   free (ctx->digest);
293   free (ctx);
294 }
295 
296 struct dsa_ctx
297 {
298   struct dsa_params params;
299   mpz_t pub;
300   mpz_t key;
301   struct knuth_lfib_ctx lfib;
302   struct dsa_signature s;
303   uint8_t *digest;
304 };
305 
306 static void *
bench_dsa_init(unsigned size)307 bench_dsa_init (unsigned size)
308 {
309   struct dsa_ctx *ctx;
310   struct sexp_iterator i;
311 
312   unsigned char dsa1024[] =
313     "{KDExOnByaXZhdGUta2V5KDM6ZHNhKDE6cDEyOToA2q4hOXEClLMXXMOl9xaPcGC/GeGmCMv"
314     " VCaaW0uWc50DvvmJDPQPdCehyfZr/1dv2UDbx06TC7ls/IFd+BsDzGBRxqIQ44J20cn+0gt"
315     " NMIXAocE1QhCCFaT5gXrk8zMlqBEGaP3RdpgxNanEXkTj2Wma8r1GtrLX3HPafio62jicpK"
316     " DE6cTIxOgDN9pcW3exdVAesC9WsxwCGoJK24ykoMTpnMTI5OgCJr9DmKdiE0WJZB7HACESv"
317     " Tpg1qZgc8E15byQ+OsHUyOTRrJRTcrgKZJW7dFRJ9cXmyi7XYCd3bJtu/2HRHLY1vd4qMvU"
318     " 7Y8x08ooCoABGV7nGqcmdQfEho1OY6TZh2NikmPKZLeur3PZFpcZ8Dl+KVWtwC55plNC7Om"
319     " iAQy8MaCkoMTp5MTI5OgDakk0LOUQwzOKt9FHOBmBKrWsvTm7549eScTUqH4OMm3btjUsXz"
320     " MmlqEe+imwQCOW/AE3Xw9pXZeETWK0jlLe8k5vnKcNskerFwZ1eQKtOPPQty8IqQ9PEfF6B"
321     " 0oVQiJg2maHUDWFnDkIBd7ZR1z8FnZMUxH9mH4kEUo6YQgtCdykoMTp4MjA6cOl3ijiiMjI"
322     " pesFD8jxESWb2mn8pKSk=}";
323 
324   ctx = xalloc(sizeof(*ctx));
325 
326   dsa_params_init (&ctx->params);
327   mpz_init (ctx->pub);
328   mpz_init (ctx->key);
329   dsa_signature_init (&ctx->s);
330   knuth_lfib_init (&ctx->lfib, 1);
331 
332   if (size != 1024)
333     die ("Internal error.\n");
334 
335   if (! (sexp_transport_iterator_first (&i, sizeof(dsa1024) - 1, dsa1024)
336 	 && sexp_iterator_check_type (&i, "private-key")
337 	 && sexp_iterator_check_type (&i, "dsa")
338 	 && dsa_keypair_from_sexp_alist (&ctx->params, ctx->pub, ctx->key,
339 					 0, DSA_SHA1_Q_BITS, &i)) )
340     die ("Internal error.\n");
341 
342   ctx->digest = hash_string (&nettle_sha1, "foo");
343 
344   dsa_sign (&ctx->params, ctx->key,
345 	    &ctx->lfib, (nettle_random_func *)knuth_lfib_random,
346 	    SHA1_DIGEST_SIZE, ctx->digest, &ctx->s);
347 
348   return ctx;
349 }
350 
351 static void
bench_dsa_sign(void * p)352 bench_dsa_sign (void *p)
353 {
354   struct dsa_ctx *ctx = p;
355   struct dsa_signature s;
356 
357   dsa_signature_init (&s);
358   dsa_sign (&ctx->params, ctx->key,
359 	    &ctx->lfib, (nettle_random_func *)knuth_lfib_random,
360 	    SHA1_DIGEST_SIZE, ctx->digest, &s);
361   dsa_signature_clear (&s);
362 }
363 
364 static void
bench_dsa_verify(void * p)365 bench_dsa_verify (void *p)
366 {
367   struct dsa_ctx *ctx = p;
368   if (! dsa_verify (&ctx->params, ctx->pub, SHA1_DIGEST_SIZE, ctx->digest, &ctx->s))
369     die ("Internal error, dsa_sha1_verify_digest failed.\n");
370 }
371 
372 static void
bench_dsa_clear(void * p)373 bench_dsa_clear (void *p)
374 {
375   struct dsa_ctx *ctx = p;
376   dsa_params_clear (&ctx->params);
377   mpz_clear (ctx->pub);
378   mpz_clear (ctx->key);
379   dsa_signature_clear (&ctx->s);
380   free (ctx->digest);
381   free (ctx);
382 }
383 
384 struct ecdsa_ctx
385 {
386   struct ecc_point pub;
387   struct ecc_scalar key;
388   struct knuth_lfib_ctx rctx;
389   unsigned digest_size;
390   uint8_t *digest;
391   struct dsa_signature s;
392 };
393 
394 static void *
bench_ecdsa_init(unsigned size)395 bench_ecdsa_init (unsigned size)
396 {
397   struct ecdsa_ctx *ctx;
398   const struct ecc_curve *ecc;
399 
400   const char *xs;
401   const char *ys;
402   const char *zs;
403   mpz_t x, y, z;
404 
405   ctx = xalloc (sizeof(*ctx));
406 
407   dsa_signature_init (&ctx->s);
408   knuth_lfib_init (&ctx->rctx, 17);
409 
410   switch (size)
411     {
412     case 192:
413       ecc = &_nettle_secp_192r1;
414       xs = "8e8e07360350fb6b7ad8370cfd32fa8c6bba785e6e200599";
415       ys = "7f82ddb58a43d59ff8dc66053002b918b99bd01bd68d6736";
416       zs = "f2e620e086d658b4b507996988480917640e4dc107808bdd";
417       ctx->digest = hash_string (&nettle_sha1, "abc");
418       ctx->digest_size = 20;
419       break;
420     case 224:
421       ecc = &_nettle_secp_224r1;
422       xs = "993bf363f4f2bc0f255f22563980449164e9c894d9efd088d7b77334";
423       ys = "b75fff9849997d02d135140e4d0030944589586e22df1fc4b629082a";
424       zs = "cdfd01838247f5de3cc70b688418046f10a2bfaca6de9ec836d48c27";
425       ctx->digest = hash_string (&nettle_sha224, "abc");
426       ctx->digest_size = 28;
427       break;
428 
429       /* From RFC 4754 */
430     case 256:
431       ecc = &_nettle_secp_256r1;
432       xs = "2442A5CC 0ECD015F A3CA31DC 8E2BBC70 BF42D60C BCA20085 E0822CB0 4235E970";
433       ys = "6FC98BD7 E50211A4 A27102FA 3549DF79 EBCB4BF2 46B80945 CDDFE7D5 09BBFD7D";
434       zs = "DC51D386 6A15BACD E33D96F9 92FCA99D A7E6EF09 34E70975 59C27F16 14C88A7F";
435       ctx->digest = hash_string (&nettle_sha256, "abc");
436       ctx->digest_size = 32;
437       break;
438     case 384:
439       ecc = &_nettle_secp_384r1;
440       xs = "96281BF8 DD5E0525 CA049C04 8D345D30 82968D10 FEDF5C5A CA0C64E6 465A97EA"
441 	"5CE10C9D FEC21797 41571072 1F437922";
442       ys = "447688BA 94708EB6 E2E4D59F 6AB6D7ED FF9301D2 49FE49C3 3096655F 5D502FAD"
443 	"3D383B91 C5E7EDAA 2B714CC9 9D5743CA";
444       zs = "0BEB6466 34BA8773 5D77AE48 09A0EBEA 865535DE 4C1E1DCB 692E8470 8E81A5AF"
445 	"62E528C3 8B2A81B3 5309668D 73524D9F";
446       ctx->digest = hash_string (&nettle_sha384, "abc");
447       ctx->digest_size = 48;
448       break;
449     case 521:
450       ecc = &_nettle_secp_521r1;
451       xs = "0151518F 1AF0F563 517EDD54 85190DF9 5A4BF57B 5CBA4CF2 A9A3F647 4725A35F"
452 	"7AFE0A6D DEB8BEDB CD6A197E 592D4018 8901CECD 650699C9 B5E456AE A5ADD190"
453 	"52A8";
454       ys = "006F3B14 2EA1BFFF 7E2837AD 44C9E4FF 6D2D34C7 3184BBAD 90026DD5 E6E85317"
455 	"D9DF45CA D7803C6C 20035B2F 3FF63AFF 4E1BA64D 1C077577 DA3F4286 C58F0AEA"
456 	"E643";
457       zs = "0065FDA3 409451DC AB0A0EAD 45495112 A3D813C1 7BFD34BD F8C1209D 7DF58491"
458 	"20597779 060A7FF9 D704ADF7 8B570FFA D6F062E9 5C7E0C5D 5481C5B1 53B48B37"
459 	"5FA1";
460 
461       ctx->digest = hash_string (&nettle_sha512, "abc");
462       ctx->digest_size = 64;
463       break;
464     default:
465       die ("Internal error.\n");
466     }
467   ecc_point_init (&ctx->pub, ecc);
468   ecc_scalar_init (&ctx->key, ecc);
469 
470   mpz_init_set_str (x, xs, 16);
471   mpz_init_set_str (y, ys, 16);
472   mpz_init_set_str (z, zs, 16);
473 
474   ecc_point_set (&ctx->pub, x, y);
475   ecc_scalar_set (&ctx->key, z);
476 
477   mpz_clear (x);
478   mpz_clear (y);
479   mpz_clear (z);
480 
481   ecdsa_sign (&ctx->key,
482 	      &ctx->rctx, (nettle_random_func *) knuth_lfib_random,
483 	      ctx->digest_size, ctx->digest,
484 	      &ctx->s);
485 
486   return ctx;
487 }
488 
489 static void
bench_ecdsa_sign(void * p)490 bench_ecdsa_sign (void *p)
491 {
492   struct ecdsa_ctx *ctx = p;
493   struct dsa_signature s;
494 
495   dsa_signature_init (&s);
496   ecdsa_sign (&ctx->key,
497 	      &ctx->rctx, (nettle_random_func *) knuth_lfib_random,
498 	      ctx->digest_size, ctx->digest,
499 	      &s);
500   dsa_signature_clear (&s);
501 }
502 
503 static void
bench_ecdsa_verify(void * p)504 bench_ecdsa_verify (void *p)
505 {
506   struct ecdsa_ctx *ctx = p;
507   if (! ecdsa_verify (&ctx->pub,
508 		      ctx->digest_size, ctx->digest,
509 		      &ctx->s))
510     die ("Internal error, _ecdsa_verify failed.\n");
511 }
512 
513 static void
bench_ecdsa_clear(void * p)514 bench_ecdsa_clear (void *p)
515 {
516   struct ecdsa_ctx *ctx = p;
517 
518   ecc_point_clear (&ctx->pub);
519   ecc_scalar_clear (&ctx->key);
520   dsa_signature_clear (&ctx->s);
521   free (ctx->digest);
522 
523   free (ctx);
524 }
525 
526 #if WITH_OPENSSL
527 struct openssl_rsa_ctx
528 {
529   RSA *key;
530   unsigned char *ref;
531   unsigned char *signature;
532   unsigned int siglen;
533   uint8_t *digest;
534 };
535 
536 static struct openssl_rsa_ctx*
make_openssl_rsa_ctx(unsigned size)537 make_openssl_rsa_ctx (unsigned size)
538 {
539   struct openssl_rsa_ctx *ctx = xalloc (sizeof (*ctx));
540   BIGNUM *e = BN_new();
541   BN_set_word(e, 65537);
542   ctx->key = RSA_new();
543   RSA_generate_key_ex (ctx->key, size, e, NULL);
544   ctx->ref = xalloc (RSA_size (ctx->key));
545   ctx->signature = xalloc (RSA_size (ctx->key));
546   ctx->digest = hash_string (&nettle_sha1, "foo");
547 
548   if (! RSA_sign (NID_sha1, ctx->digest, SHA1_DIGEST_SIZE,
549 		  ctx->ref, &ctx->siglen, ctx->key))
550     die ("OpenSSL RSA_sign failed.\n");
551 
552   BN_free(e);
553   return ctx;
554 }
555 
556 static void *
bench_openssl_rsa_init(unsigned size)557 bench_openssl_rsa_init (unsigned size)
558 {
559   struct openssl_rsa_ctx *ctx = make_openssl_rsa_ctx (size);
560   RSA_blinding_off(ctx->key);
561   return ctx;
562 }
563 
564 static void *
bench_openssl_rsa_tr_init(unsigned size)565 bench_openssl_rsa_tr_init (unsigned size)
566 {
567   return make_openssl_rsa_ctx (size);
568 }
569 
570 static void
bench_openssl_rsa_sign(void * p)571 bench_openssl_rsa_sign (void *p)
572 {
573   const struct openssl_rsa_ctx *ctx = p;
574   unsigned siglen;
575 
576   if (! RSA_sign (NID_sha1, ctx->digest, SHA1_DIGEST_SIZE,
577 		  ctx->signature, &siglen, ctx->key))
578     die ("OpenSSL RSA_sign failed.\n");
579 }
580 
581 static void
bench_openssl_rsa_verify(void * p)582 bench_openssl_rsa_verify (void *p)
583 {
584   const struct openssl_rsa_ctx *ctx = p;
585   if (! RSA_verify (NID_sha1, ctx->digest, SHA1_DIGEST_SIZE,
586 		    ctx->ref, ctx->siglen, ctx->key))
587     die ("OpenSSL RSA_verify failed.\n");
588 }
589 
590 static void
bench_openssl_rsa_clear(void * p)591 bench_openssl_rsa_clear (void *p)
592 {
593   struct openssl_rsa_ctx *ctx = p;
594   RSA_free (ctx->key);
595   free (ctx->ref);
596   free (ctx->signature);
597   free (ctx->digest);
598   free (ctx);
599 }
600 
601 struct openssl_ecdsa_ctx
602 {
603   EC_KEY *key;
604   ECDSA_SIG *signature;
605   unsigned digest_length;
606   uint8_t *digest;
607 };
608 
609 static void *
bench_openssl_ecdsa_init(unsigned size)610 bench_openssl_ecdsa_init (unsigned size)
611 {
612   struct openssl_ecdsa_ctx *ctx = xalloc (sizeof (*ctx));
613 
614   switch (size)
615     {
616     case 192:
617       ctx->key = EC_KEY_new_by_curve_name (NID_X9_62_prime192v1);
618       ctx->digest_length = 24; /* truncated */
619       ctx->digest = hash_string (&nettle_sha224, "abc");
620       break;
621     case 224:
622       ctx->key = EC_KEY_new_by_curve_name (NID_secp224r1);
623       ctx->digest_length = SHA224_DIGEST_SIZE;
624       ctx->digest = hash_string (&nettle_sha224, "abc");
625       break;
626     case 256:
627       ctx->key = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
628       ctx->digest_length = SHA256_DIGEST_SIZE;
629       ctx->digest = hash_string (&nettle_sha256, "abc");
630       break;
631     case 384:
632       ctx->key = EC_KEY_new_by_curve_name (NID_secp384r1);
633       ctx->digest_length = SHA384_DIGEST_SIZE;
634       ctx->digest = hash_string (&nettle_sha384, "abc");
635       break;
636     case 521:
637       ctx->key = EC_KEY_new_by_curve_name (NID_secp521r1);
638       ctx->digest_length = SHA512_DIGEST_SIZE;
639       ctx->digest = hash_string (&nettle_sha512, "abc");
640       break;
641     default:
642       die ("Internal error.\n");
643     }
644 
645   /* This curve isn't supported in this build of openssl */
646   if (ctx->key == NULL)
647     {
648       free(ctx);
649       return NULL;
650     }
651 
652   if (!EC_KEY_generate_key( ctx->key))
653     die ("Openssl EC_KEY_generate_key failed.\n");
654 
655   ctx->signature = ECDSA_do_sign (ctx->digest, ctx->digest_length, ctx->key);
656 
657   return ctx;
658 }
659 
660 static void
bench_openssl_ecdsa_sign(void * p)661 bench_openssl_ecdsa_sign (void *p)
662 {
663   const struct openssl_ecdsa_ctx *ctx = p;
664   ECDSA_SIG *sig = ECDSA_do_sign (ctx->digest, ctx->digest_length, ctx->key);
665   ECDSA_SIG_free (sig);
666 }
667 
668 static void
bench_openssl_ecdsa_verify(void * p)669 bench_openssl_ecdsa_verify (void *p)
670 {
671   const struct openssl_ecdsa_ctx *ctx = p;
672   if (ECDSA_do_verify (ctx->digest, ctx->digest_length,
673 			 ctx->signature, ctx->key) != 1)
674     die ("Openssl ECDSA_do_verify failed.\n");
675 }
676 static void
bench_openssl_ecdsa_clear(void * p)677 bench_openssl_ecdsa_clear (void *p)
678 {
679   struct openssl_ecdsa_ctx *ctx = p;
680   ECDSA_SIG_free (ctx->signature);
681   EC_KEY_free (ctx->key);
682   free (ctx->digest);
683   free (ctx);
684 }
685 #endif
686 
687 struct curve25519_ctx
688 {
689   uint8_t x[CURVE25519_SIZE];
690   uint8_t s[CURVE25519_SIZE];
691 };
692 
693 static void
bench_curve25519_mul_g(void * p)694 bench_curve25519_mul_g (void *p)
695 {
696   struct curve25519_ctx *ctx = p;
697   uint8_t q[CURVE25519_SIZE];
698   curve25519_mul_g (q, ctx->s);
699 }
700 
701 static void
bench_curve25519_mul(void * p)702 bench_curve25519_mul (void *p)
703 {
704   struct curve25519_ctx *ctx = p;
705   uint8_t q[CURVE25519_SIZE];
706   curve25519_mul (q, ctx->s, ctx->x);
707 }
708 
709 static void
bench_curve25519(void)710 bench_curve25519 (void)
711 {
712   double mul_g;
713   double mul;
714   struct knuth_lfib_ctx lfib;
715   struct curve25519_ctx ctx;
716   knuth_lfib_init (&lfib, 2);
717 
718   knuth_lfib_random (&lfib, sizeof(ctx.s), ctx.s);
719   curve25519_mul_g (ctx.x, ctx.s);
720 
721   mul_g = time_function (bench_curve25519_mul_g, &ctx);
722   mul = time_function (bench_curve25519_mul, &ctx);
723 
724   printf("%16s %4d %9.4f %9.4f\n",
725 	 "curve25519", 255, 1e-3/mul_g, 1e-3/mul);
726 }
727 
728 struct alg alg_list[] = {
729   { "rsa",   1024, bench_rsa_init,   bench_rsa_sign,   bench_rsa_verify,   bench_rsa_clear },
730   { "rsa",   2048, bench_rsa_init,   bench_rsa_sign,   bench_rsa_verify,   bench_rsa_clear },
731   { "rsa-tr",   1024, bench_rsa_init,   bench_rsa_sign_tr,   bench_rsa_verify,   bench_rsa_clear },
732   { "rsa-tr",   2048, bench_rsa_init,   bench_rsa_sign_tr,   bench_rsa_verify,   bench_rsa_clear },
733 #if WITH_OPENSSL
734   { "rsa (openssl)",  1024, bench_openssl_rsa_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
735   { "rsa (openssl)",  2048, bench_openssl_rsa_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
736   { "rsa-tr (openssl)",  1024, bench_openssl_rsa_tr_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
737   { "rsa-tr (openssl)",  2048, bench_openssl_rsa_tr_init, bench_openssl_rsa_sign, bench_openssl_rsa_verify, bench_openssl_rsa_clear },
738 #endif
739   { "dsa",   1024, bench_dsa_init,   bench_dsa_sign,   bench_dsa_verify,   bench_dsa_clear },
740 #if 0
741   { "dsa",2048, bench_dsa_init, bench_dsa_sign,   bench_dsa_verify, bench_dsa_clear },
742 #endif
743   { "ecdsa",  192, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
744   { "ecdsa",  224, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
745   { "ecdsa",  256, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
746   { "ecdsa",  384, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
747   { "ecdsa",  521, bench_ecdsa_init, bench_ecdsa_sign, bench_ecdsa_verify, bench_ecdsa_clear },
748 #if WITH_OPENSSL
749   { "ecdsa (openssl)",  192, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
750   { "ecdsa (openssl)",  224, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
751   { "ecdsa (openssl)",  256, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
752   { "ecdsa (openssl)",  384, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
753   { "ecdsa (openssl)",  521, bench_openssl_ecdsa_init, bench_openssl_ecdsa_sign, bench_openssl_ecdsa_verify, bench_openssl_ecdsa_clear },
754 #endif
755 };
756 
757 #define numberof(x)  (sizeof (x) / sizeof ((x)[0]))
758 
759 int
main(int argc,char ** argv)760 main (int argc, char **argv)
761 {
762   const char *filter = NULL;
763   unsigned i;
764 
765   if (argc > 1)
766     filter = argv[1];
767 
768   time_init();
769   printf ("%16s %4s %9s %9s\n",
770 	  "name", "size", "sign/ms", "verify/ms");
771 
772   for (i = 0; i < numberof(alg_list); i++)
773     if (!filter || strstr (alg_list[i].name, filter))
774       bench_alg (&alg_list[i]);
775 
776   if (!filter || strstr("curve25519", filter))
777     bench_curve25519();
778 
779   return EXIT_SUCCESS;
780 }
781