LCOV - code coverage report
Current view: top level - tests - t-cv25519.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 165 225 73.3 %
Date: 2017-03-02 16:44:37 Functions: 8 9 88.9 %

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

Generated by: LCOV version 1.13