Line data Source code
1 : /* t-cv25519.c - Check the cv25519 crypto
2 : * Copyright (C) 2016 g10 Code GmbH
3 : *
4 : * This file is part of Libgcrypt.
5 : *
6 : * Libgcrypt is free software; you can redistribute it and/or modify
7 : * it under the terms of the GNU Lesser General Public License as
8 : * published by the Free Software Foundation; either version 2.1 of
9 : * the License, or (at your option) any later version.
10 : *
11 : * Libgcrypt is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : * GNU Lesser General Public License for more details.
15 : *
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #ifdef HAVE_CONFIG_H
21 : #include <config.h>
22 : #endif
23 : #include <stdarg.h>
24 : #include <stdio.h>
25 : #include <ctype.h>
26 : #include <stdlib.h>
27 : #include <string.h>
28 : #include <errno.h>
29 :
30 : #include "../src/gcrypt-int.h"
31 :
32 : #include "stopwatch.h"
33 :
34 : #define PGM "t-cv25519"
35 : #define N_TESTS 18
36 :
37 : #define my_isascii(c) (!((c) & 0x80))
38 : #define digitp(p) (*(p) >= '0' && *(p) <= '9')
39 : #define hexdigitp(a) (digitp (a) \
40 : || (*(a) >= 'A' && *(a) <= 'F') \
41 : || (*(a) >= 'a' && *(a) <= 'f'))
42 : #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
43 : *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
44 : #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
45 : #define xmalloc(a) gcry_xmalloc ((a))
46 : #define xcalloc(a,b) gcry_xcalloc ((a),(b))
47 : #define xstrdup(a) gcry_xstrdup ((a))
48 : #define xfree(a) gcry_free ((a))
49 : #define pass() do { ; } while (0)
50 :
51 : static int verbose;
52 : static int debug;
53 : static int error_count;
54 :
55 : static void
56 0 : print_mpi (const char *text, gcry_mpi_t a)
57 : {
58 : gcry_error_t err;
59 : char *buf;
60 0 : void *bufaddr = &buf;
61 :
62 0 : err = gcry_mpi_aprint (GCRYMPI_FMT_HEX, bufaddr, NULL, a);
63 0 : if (err)
64 0 : fprintf (stderr, "%s: [error printing number: %s]\n",
65 : text, gpg_strerror (err));
66 : else
67 : {
68 0 : fprintf (stderr, "%s: %s\n", text, buf);
69 0 : gcry_free (buf);
70 : }
71 0 : }
72 :
73 : static void
74 0 : die (const char *format, ...)
75 : {
76 : va_list arg_ptr ;
77 :
78 0 : fflush (stdout);
79 0 : fprintf (stderr, "%s: ", PGM);
80 0 : va_start( arg_ptr, format ) ;
81 0 : vfprintf (stderr, format, arg_ptr );
82 0 : va_end(arg_ptr);
83 0 : if (*format && format[strlen(format)-1] != '\n')
84 0 : putc ('\n', stderr);
85 0 : exit (1);
86 : }
87 :
88 : static void
89 0 : fail (const char *format, ...)
90 : {
91 : va_list arg_ptr;
92 :
93 0 : fflush (stdout);
94 0 : fprintf (stderr, "%s: ", PGM);
95 : /* if (wherestr) */
96 : /* fprintf (stderr, "%s: ", wherestr); */
97 0 : va_start (arg_ptr, format);
98 0 : vfprintf (stderr, format, arg_ptr);
99 0 : va_end (arg_ptr);
100 0 : if (*format && format[strlen(format)-1] != '\n')
101 0 : putc ('\n', stderr);
102 0 : error_count++;
103 0 : if (error_count >= 50)
104 0 : die ("stopped after 50 errors.");
105 0 : }
106 :
107 : static void
108 2 : show (const char *format, ...)
109 : {
110 : va_list arg_ptr;
111 :
112 2 : if (!verbose)
113 4 : return;
114 0 : fprintf (stderr, "%s: ", PGM);
115 0 : va_start (arg_ptr, format);
116 0 : vfprintf (stderr, format, arg_ptr);
117 0 : if (*format && format[strlen(format)-1] != '\n')
118 0 : putc ('\n', stderr);
119 0 : va_end (arg_ptr);
120 : }
121 :
122 :
123 : static void
124 1 : show_note (const char *format, ...)
125 : {
126 : va_list arg_ptr;
127 :
128 1 : if (!verbose && getenv ("srcdir"))
129 1 : fputs (" ", stderr); /* To align above "PASS: ". */
130 : else
131 0 : fprintf (stderr, "%s: ", PGM);
132 1 : va_start (arg_ptr, format);
133 1 : vfprintf (stderr, format, arg_ptr);
134 1 : if (*format && format[strlen(format)-1] != '\n')
135 0 : putc ('\n', stderr);
136 1 : va_end (arg_ptr);
137 1 : }
138 :
139 :
140 : /* Convert STRING consisting of hex characters into its binary
141 : representation and return it as an allocated buffer. The valid
142 : length of the buffer is returned at R_LENGTH. The string is
143 : delimited by end of string. The function returns NULL on
144 : error. */
145 : static void *
146 40 : hex2buffer (const char *string, size_t *r_length)
147 : {
148 : const char *s;
149 : unsigned char *buffer;
150 : size_t length;
151 :
152 40 : buffer = xmalloc (strlen(string)/2+1);
153 40 : length = 0;
154 1320 : for (s=string; *s; s +=2 )
155 : {
156 1280 : if (!hexdigitp (s) || !hexdigitp (s+1))
157 0 : return NULL; /* Invalid hex digits. */
158 1280 : ((unsigned char*)buffer)[length++] = xtoi_2 (s);
159 : }
160 40 : *r_length = length;
161 40 : return buffer;
162 : }
163 :
164 : static void
165 23 : reverse_buffer (unsigned char *buffer, unsigned int length)
166 : {
167 : unsigned int tmp, i;
168 :
169 391 : for (i=0; i < length/2; i++)
170 : {
171 368 : tmp = buffer[i];
172 368 : buffer[i] = buffer[length-1-i];
173 368 : buffer[length-1-i] = tmp;
174 : }
175 23 : }
176 :
177 :
178 : /*
179 : * Test X25519 functionality through higher layer crypto routines.
180 : *
181 : * Input: K (as hex string), U (as hex string), R (as hex string)
182 : *
183 : * where R is expected result of X25519 (K, U).
184 : *
185 : * It calls gcry_pk_decrypt with Curve25519 private key and let
186 : * it compute X25519.
187 : */
188 : static void
189 19 : test_cv (int testno, const char *k_str, const char *u_str,
190 : const char *result_str)
191 : {
192 : gpg_error_t err;
193 19 : void *buffer = NULL;
194 : size_t buflen;
195 19 : gcry_sexp_t s_pk = NULL;
196 19 : gcry_mpi_t mpi_k = NULL;
197 19 : gcry_sexp_t s_data = NULL;
198 19 : gcry_sexp_t s_result = NULL;
199 19 : gcry_sexp_t s_tmp = NULL;
200 19 : unsigned char *res = NULL;
201 : size_t res_len;
202 :
203 19 : if (verbose > 1)
204 0 : show ("Running test %d\n", testno);
205 :
206 19 : if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32)
207 : {
208 0 : fail ("error building s-exp for test %d, %s: %s",
209 : testno, "k", "invalid hex string");
210 0 : goto leave;
211 : }
212 :
213 19 : reverse_buffer (buffer, buflen);
214 19 : if ((err = gcry_mpi_scan (&mpi_k, GCRYMPI_FMT_USG, buffer, buflen, NULL)))
215 : {
216 0 : fail ("error converting MPI for test %d: %s", testno, gpg_strerror (err));
217 0 : goto leave;
218 : }
219 :
220 19 : if ((err = gcry_sexp_build (&s_data, NULL, "%m", mpi_k)))
221 : {
222 0 : fail ("error building s-exp for test %d, %s: %s",
223 : testno, "data", gpg_strerror (err));
224 0 : goto leave;
225 : }
226 :
227 19 : xfree (buffer);
228 19 : if (!(buffer = hex2buffer (u_str, &buflen)) || buflen != 32)
229 : {
230 0 : fail ("error building s-exp for test %d, %s: %s",
231 : testno, "u", "invalid hex string");
232 0 : goto leave;
233 : }
234 :
235 : /*
236 : * The procedure of decodeUCoordinate will be done internally
237 : * by _gcry_ecc_mont_decodepoint. So, we just put the little-endian
238 : * binary to build S-exp.
239 : *
240 : * We could add the prefix 0x40, but libgcrypt also supports
241 : * format with no prefix. So, it is OK not to put the prefix.
242 : */
243 19 : if ((err = gcry_sexp_build (&s_pk, NULL,
244 : "(public-key"
245 : " (ecc"
246 : " (curve \"Curve25519\")"
247 : " (flags djb-tweak)"
248 : " (q%b)))", (int)buflen, buffer)))
249 : {
250 0 : fail ("error building s-exp for test %d, %s: %s",
251 : testno, "pk", gpg_strerror (err));
252 0 : goto leave;
253 : }
254 :
255 19 : xfree (buffer);
256 19 : buffer = NULL;
257 :
258 19 : if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk)))
259 0 : fail ("gcry_pk_encrypt failed for test %d: %s", testno,
260 : gpg_strerror (err));
261 :
262 19 : s_tmp = gcry_sexp_find_token (s_result, "s", 0);
263 19 : if (!s_tmp || !(res = gcry_sexp_nth_buffer (s_tmp, 1, &res_len)))
264 0 : fail ("gcry_pk_encrypt failed for test %d: %s", testno, "missing value");
265 : else
266 : {
267 : char *r, *r0;
268 : int i;
269 :
270 : /* To skip the prefix 0x40, for-loop start with i=1 */
271 19 : r0 = r = xmalloc (2*(res_len)+1);
272 19 : if (!r0)
273 : {
274 0 : fail ("memory allocation", testno);
275 0 : goto leave;
276 : }
277 :
278 627 : for (i=1; i < res_len; i++, r += 2)
279 608 : snprintf (r, 3, "%02x", res[i]);
280 19 : if (strcmp (result_str, r0))
281 : {
282 0 : fail ("gcry_pk_encrypt failed for test %d: %s",
283 : testno, "wrong value returned");
284 0 : show (" expected: '%s'", result_str);
285 0 : show (" got: '%s'", r0);
286 : }
287 19 : xfree (r0);
288 : }
289 :
290 : leave:
291 19 : xfree (res);
292 19 : gcry_mpi_release (mpi_k);
293 19 : gcry_sexp_release (s_tmp);
294 19 : gcry_sexp_release (s_result);
295 19 : gcry_sexp_release (s_data);
296 19 : gcry_sexp_release (s_pk);
297 19 : xfree (buffer);
298 19 : }
299 :
300 : /*
301 : * Test iterative X25519 computation through lower layer MPI routines.
302 : *
303 : * Input: K (as hex string), ITER, R (as hex string)
304 : *
305 : * where R is expected result of iterating X25519 by ITER times.
306 : *
307 : */
308 : static void
309 2 : test_it (int testno, const char *k_str, int iter, const char *result_str)
310 : {
311 : gcry_ctx_t ctx;
312 : gpg_error_t err;
313 2 : void *buffer = NULL;
314 : size_t buflen;
315 2 : gcry_mpi_t mpi_k = NULL;
316 2 : gcry_mpi_t mpi_x = NULL;
317 2 : gcry_mpi_point_t P = NULL;
318 : gcry_mpi_point_t Q;
319 : int i;
320 2 : gcry_mpi_t mpi_kk = NULL;
321 :
322 2 : if (verbose > 1)
323 0 : show ("Running test %d: iteration=%d\n", testno, iter);
324 :
325 2 : gcry_mpi_ec_new (&ctx, NULL, "Curve25519");
326 2 : Q = gcry_mpi_point_new (0);
327 :
328 2 : if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32)
329 : {
330 0 : fail ("error scanning MPI for test %d, %s: %s",
331 : testno, "k", "invalid hex string");
332 0 : goto leave;
333 : }
334 2 : reverse_buffer (buffer, buflen);
335 2 : if ((err = gcry_mpi_scan (&mpi_x, GCRYMPI_FMT_USG, buffer, buflen, NULL)))
336 : {
337 0 : fail ("error scanning MPI for test %d, %s: %s",
338 : testno, "x", gpg_strerror (err));
339 0 : goto leave;
340 : }
341 :
342 2 : xfree (buffer);
343 2 : buffer = NULL;
344 :
345 2 : P = gcry_mpi_point_set (NULL, mpi_x, NULL, GCRYMPI_CONST_ONE);
346 :
347 2 : mpi_k = gcry_mpi_copy (mpi_x);
348 2 : if (debug)
349 0 : print_mpi ("k", mpi_k);
350 :
351 1003 : for (i = 0; i < iter; i++)
352 : {
353 : /*
354 : * Another variant of decodeScalar25519 thing.
355 : */
356 1001 : mpi_kk = gcry_mpi_set (mpi_kk, mpi_k);
357 1001 : gcry_mpi_set_bit (mpi_kk, 254);
358 1001 : gcry_mpi_clear_bit (mpi_kk, 255);
359 1001 : gcry_mpi_clear_bit (mpi_kk, 0);
360 1001 : gcry_mpi_clear_bit (mpi_kk, 1);
361 1001 : gcry_mpi_clear_bit (mpi_kk, 2);
362 :
363 1001 : gcry_mpi_ec_mul (Q, mpi_kk, P, ctx);
364 :
365 1001 : P = gcry_mpi_point_set (P, mpi_k, NULL, GCRYMPI_CONST_ONE);
366 1001 : gcry_mpi_ec_get_affine (mpi_k, NULL, Q, ctx);
367 :
368 1001 : if (debug)
369 0 : print_mpi ("k", mpi_k);
370 : }
371 :
372 : {
373 : unsigned char res[32];
374 : char *r, *r0;
375 :
376 2 : gcry_mpi_print (GCRYMPI_FMT_USG, res, 32, NULL, mpi_k);
377 2 : reverse_buffer (res, 32);
378 :
379 2 : r0 = r = xmalloc (65);
380 2 : if (!r0)
381 : {
382 0 : fail ("memory allocation", testno);
383 0 : goto leave;
384 : }
385 :
386 66 : for (i=0; i < 32; i++, r += 2)
387 64 : snprintf (r, 3, "%02x", res[i]);
388 :
389 2 : if (strcmp (result_str, r0))
390 : {
391 0 : fail ("curv25519 failed for test %d: %s",
392 : testno, "wrong value returned");
393 0 : show (" expected: '%s'", result_str);
394 0 : show (" got: '%s'", r0);
395 : }
396 2 : xfree (r0);
397 : }
398 :
399 : leave:
400 2 : gcry_mpi_release (mpi_kk);
401 2 : gcry_mpi_release (mpi_k);
402 2 : gcry_mpi_point_release (P);
403 2 : gcry_mpi_release (mpi_x);
404 2 : xfree (buffer);
405 2 : gcry_mpi_point_release (Q);
406 2 : gcry_ctx_release (ctx);
407 2 : }
408 :
409 : /*
410 : * X-coordinate of generator of the Curve25519.
411 : */
412 : #define G_X "0900000000000000000000000000000000000000000000000000000000000000"
413 :
414 : /*
415 : * Test Diffie-Hellman in RFC-7748.
416 : *
417 : * Note that it's not like the ECDH of OpenPGP, where we use
418 : * ephemeral public key.
419 : */
420 : static void
421 1 : test_dh (int testno, const char *a_priv_str, const char *a_pub_str,
422 : const char *b_priv_str, const char *b_pub_str,
423 : const char *result_str)
424 : {
425 : /* Test A for private key corresponds to public key. */
426 1 : test_cv (testno, a_priv_str, G_X, a_pub_str);
427 : /* Test B for private key corresponds to public key. */
428 1 : test_cv (testno, b_priv_str, G_X, b_pub_str);
429 : /* Test DH with A's private key and B's public key. */
430 1 : test_cv (testno, a_priv_str, b_pub_str, result_str);
431 : /* Test DH with B's private key and A's public key. */
432 1 : test_cv (testno, b_priv_str, a_pub_str, result_str);
433 1 : }
434 :
435 :
436 : static void
437 1 : check_cv25519 (void)
438 : {
439 : int ntests;
440 :
441 1 : show ("Checking Curve25519.\n");
442 :
443 1 : ntests = 0;
444 :
445 : /*
446 : * Values are cited from RFC-7748: 5.2. Test Vectors.
447 : * Following two tests are for the first type test.
448 : */
449 1 : test_cv (1,
450 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
451 : "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c",
452 : "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552");
453 1 : ntests++;
454 1 : test_cv (2,
455 : "4b66e9d4d1b4673c5ad22691957d6af5c11b6421e0ea01d42ca4169e7918ba0d",
456 : "e5210f12786811d3f4b7959d0538ae2c31dbe7106fc03c3efc4cd549c715a493",
457 : "95cbde9476e8907d7aade45cb4b873f88b595a68799fa152e6f8f7647aac7957");
458 1 : ntests++;
459 :
460 : /*
461 : * Additional test. Value is from second type test.
462 : */
463 1 : test_cv (3,
464 : G_X,
465 : G_X,
466 : "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079");
467 1 : ntests++;
468 :
469 : /*
470 : * Following two tests are for the second type test,
471 : * with one iteration and 1,000 iterations. (1,000,000 iterations
472 : * takes too long.)
473 : */
474 1 : test_it (4,
475 : G_X,
476 : 1,
477 : "422c8e7a6227d7bca1350b3e2bb7279f7897b87bb6854b783c60e80311ae3079");
478 1 : ntests++;
479 :
480 1 : test_it (5,
481 : G_X,
482 : 1000,
483 : "684cf59ba83309552800ef566f2f4d3c1c3887c49360e3875f2eb94d99532c51");
484 1 : ntests++;
485 :
486 : /*
487 : * Last test is from: 6. Diffie-Hellman, 6.1. Curve25519
488 : */
489 1 : test_dh (6,
490 : /* Alice's private key, a */
491 : "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
492 : /* Alice's public key, X25519(a, 9) */
493 : "8520f0098930a754748b7ddcb43ef75a0dbf3a0d26381af4eba4a98eaa9b4e6a",
494 : /* Bob's private key, b */
495 : "5dab087e624a8a4b79e17f8b83800ee66f3bb1292618b6fd1c2f8b27ff88e0eb",
496 : /* Bob's public key, X25519(b, 9) */
497 : "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
498 : /* Their shared secret, K */
499 : "4a5d9d5ba4ce2de1728e3bf480350f25e07e21c947d19e3376f09b3c1e161742");
500 1 : ntests++;
501 :
502 : /* Seven tests which results 0. */
503 1 : test_cv (7,
504 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
505 : "0000000000000000000000000000000000000000000000000000000000000000",
506 : "0000000000000000000000000000000000000000000000000000000000000000");
507 1 : ntests++;
508 :
509 1 : test_cv (8,
510 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
511 : "0100000000000000000000000000000000000000000000000000000000000000",
512 : "0000000000000000000000000000000000000000000000000000000000000000");
513 1 : ntests++;
514 :
515 1 : test_cv (9,
516 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
517 : "e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800",
518 : "0000000000000000000000000000000000000000000000000000000000000000");
519 1 : ntests++;
520 :
521 1 : test_cv (10,
522 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
523 : "5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157",
524 : "0000000000000000000000000000000000000000000000000000000000000000");
525 1 : ntests++;
526 :
527 1 : test_cv (11,
528 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
529 : "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
530 : "0000000000000000000000000000000000000000000000000000000000000000");
531 1 : ntests++;
532 :
533 1 : test_cv (12,
534 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
535 : "edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
536 : "0000000000000000000000000000000000000000000000000000000000000000");
537 1 : ntests++;
538 :
539 1 : test_cv (13,
540 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
541 : "eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f",
542 : "0000000000000000000000000000000000000000000000000000000000000000");
543 1 : ntests++;
544 :
545 : /* Five tests which resulted 0 if decodeUCoordinate didn't change MSB. */
546 1 : test_cv (14,
547 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
548 : "cdeb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b880",
549 : "7ce548bc4919008436244d2da7a9906528fe3a6d278047654bd32d8acde9707b");
550 1 : ntests++;
551 :
552 1 : test_cv (15,
553 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
554 : "4c9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f11d7",
555 : "e17902e989a034acdf7248260e2c94cdaf2fe1e72aaac7024a128058b6189939");
556 1 : ntests++;
557 :
558 1 : test_cv (16,
559 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
560 : "d9ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
561 : "ea6e6ddf0685c31e152d5818441ac9ac8db1a01f3d6cb5041b07443a901e7145");
562 1 : ntests++;
563 :
564 1 : test_cv (17,
565 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
566 : "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
567 : "845ddce7b3a9b3ee01a2f1fd4282ad293310f7a232cbc5459fb35d94bccc9d05");
568 1 : ntests++;
569 :
570 1 : test_cv (18,
571 : "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4",
572 : "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
573 : "6989e2cb1cea159acf121b0af6bf77493189c9bd32c2dac71669b540f9488247");
574 1 : ntests++;
575 :
576 1 : if (ntests != N_TESTS)
577 0 : fail ("did %d tests but expected %d", ntests, N_TESTS);
578 1 : else if ((ntests % 256))
579 1 : show_note ("%d tests done\n", ntests);
580 1 : }
581 :
582 :
583 : int
584 1 : main (int argc, char **argv)
585 : {
586 1 : int last_argc = -1;
587 :
588 1 : if (argc)
589 1 : { argc--; argv++; }
590 :
591 2 : while (argc && last_argc != argc )
592 : {
593 0 : last_argc = argc;
594 0 : if (!strcmp (*argv, "--"))
595 : {
596 0 : argc--; argv++;
597 0 : break;
598 : }
599 0 : else if (!strcmp (*argv, "--help"))
600 : {
601 0 : fputs ("usage: " PGM " [options]\n"
602 : "Options:\n"
603 : " --verbose print timings etc.\n"
604 : " --debug flyswatter\n",
605 : stdout);
606 0 : exit (0);
607 : }
608 0 : else if (!strcmp (*argv, "--verbose"))
609 : {
610 0 : verbose++;
611 0 : argc--; argv++;
612 : }
613 0 : else if (!strcmp (*argv, "--debug"))
614 : {
615 0 : verbose += 2;
616 0 : debug++;
617 0 : argc--; argv++;
618 : }
619 0 : else if (!strncmp (*argv, "--", 2))
620 0 : die ("unknown option '%s'", *argv);
621 : }
622 :
623 1 : gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
624 1 : if (!gcry_check_version (GCRYPT_VERSION))
625 0 : die ("version mismatch\n");
626 1 : if (debug)
627 0 : gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
628 1 : gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
629 1 : gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
630 :
631 1 : start_timer ();
632 1 : check_cv25519 ();
633 1 : stop_timer ();
634 :
635 1 : show ("All tests completed in %s. Errors: %d\n",
636 : elapsed_time (1), error_count);
637 1 : return !!error_count;
638 : }
|