LCOV - code coverage report
Current view: top level - tests - t-ed25519.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 164 239 68.6 %
Date: 2016-12-15 12:59:22 Functions: 9 10 90.0 %

          Line data    Source code
       1             : /* t-ed25519.c - Check the Ed25519 crypto
       2             :  * Copyright (C) 2013 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-ed25519"
      33             : #include "t-common.h"
      34             : #define N_TESTS 1026
      35             : 
      36             : static int sign_with_pk;
      37             : static int no_verify;
      38             : static int custom_data_file;
      39             : 
      40             : 
      41             : static void
      42           5 : show_note (const char *format, ...)
      43             : {
      44             :   va_list arg_ptr;
      45             : 
      46           5 :   if (!verbose && getenv ("srcdir"))
      47           5 :     fputs ("      ", stderr);  /* To align above "PASS: ".  */
      48             :   else
      49           0 :     fprintf (stderr, "%s: ", PGM);
      50           5 :   va_start (arg_ptr, format);
      51           5 :   vfprintf (stderr, format, arg_ptr);
      52           5 :   if (*format && format[strlen(format)-1] != '\n')
      53           0 :     putc ('\n', stderr);
      54           5 :   va_end (arg_ptr);
      55           5 : }
      56             : 
      57             : 
      58             : static void
      59           0 : show_sexp (const char *prefix, gcry_sexp_t a)
      60             : {
      61             :   char *buf;
      62             :   size_t size;
      63             : 
      64           0 :   fprintf (stderr, "%s: ", PGM);
      65           0 :   if (prefix)
      66           0 :     fputs (prefix, stderr);
      67           0 :   size = gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, NULL, 0);
      68           0 :   buf = xmalloc (size);
      69             : 
      70           0 :   gcry_sexp_sprint (a, GCRYSEXP_FMT_ADVANCED, buf, size);
      71           0 :   fprintf (stderr, "%.*s", (int)size, buf);
      72           0 :   gcry_free (buf);
      73           0 : }
      74             : 
      75             : 
      76             : /* Prepend FNAME with the srcdir environment variable's value and
      77             :    retrun an allocated filename. */
      78             : char *
      79           1 : prepend_srcdir (const char *fname)
      80             : {
      81             :   static const char *srcdir;
      82             :   char *result;
      83             : 
      84           1 :   if (!srcdir && !(srcdir = getenv ("srcdir")))
      85           0 :     srcdir = ".";
      86             : 
      87           1 :   result = xmalloc (strlen (srcdir) + 1 + strlen (fname) + 1);
      88           1 :   strcpy (result, srcdir);
      89           1 :   strcat (result, "/");
      90           1 :   strcat (result, fname);
      91           1 :   return result;
      92             : }
      93             : 
      94             : 
      95             : /* Read next line but skip over empty and comment lines.  Caller must
      96             :    xfree the result.  */
      97             : static char *
      98        6173 : read_textline (FILE *fp, int *lineno)
      99             : {
     100             :   char line[4096];
     101             :   char *p;
     102             : 
     103             :   do
     104             :     {
     105        6173 :       if (!fgets (line, sizeof line, fp))
     106             :         {
     107           1 :           if (feof (fp))
     108           1 :             return NULL;
     109           0 :           die ("error reading input line: %s\n", strerror (errno));
     110             :         }
     111        6172 :       ++*lineno;
     112        6172 :       p = strchr (line, '\n');
     113        6172 :       if (!p)
     114           0 :         die ("input line %d not terminated or too long\n", *lineno);
     115        6172 :       *p = 0;
     116        6172 :       for (p--;p > line && my_isascii (*p) && isspace (*p); p--)
     117           0 :         *p = 0;
     118             :     }
     119        6172 :   while (!*line || *line == '#');
     120             :   /* if (debug) */
     121             :   /*   info ("read line: '%s'\n", line); */
     122        5130 :   return xstrdup (line);
     123             : }
     124             : 
     125             : 
     126             : /* Copy the data after the tag to BUFFER.  BUFFER will be allocated as
     127             :    needed.  */
     128             : static void
     129        4104 : copy_data (char **buffer, const char *line, int lineno)
     130             : {
     131             :   const char *s;
     132             : 
     133        4104 :   xfree (*buffer);
     134        4104 :   *buffer = NULL;
     135             : 
     136        4104 :   s = strchr (line, ':');
     137        4104 :   if (!s)
     138             :     {
     139           0 :       fail ("syntax error at input line %d", lineno);
     140           0 :       return;
     141             :     }
     142        4104 :   for (s++; my_isascii (*s) && isspace (*s); s++)
     143             :     ;
     144        4104 :   *buffer = xstrdup (s);
     145             : }
     146             : 
     147             : 
     148             : /* Convert STRING consisting of hex characters into its binary
     149             :    representation and return it as an allocated buffer. The valid
     150             :    length of the buffer is returned at R_LENGTH.  The string is
     151             :    delimited by end of string.  The function returns NULL on
     152             :    error.  */
     153             : static void *
     154        3078 : hex2buffer (const char *string, size_t *r_length)
     155             : {
     156             :   const char *s;
     157             :   unsigned char *buffer;
     158             :   size_t length;
     159             : 
     160        3078 :   buffer = xmalloc (strlen(string)/2+1);
     161        3078 :   length = 0;
     162      592552 :   for (s=string; *s; s +=2 )
     163             :     {
     164      589474 :       if (!hexdigitp (s) || !hexdigitp (s+1))
     165           0 :         return NULL;           /* Invalid hex digits. */
     166      589474 :       ((unsigned char*)buffer)[length++] = xtoi_2 (s);
     167             :     }
     168        3078 :   *r_length = length;
     169        3078 :   return buffer;
     170             : }
     171             : 
     172             : 
     173             : static void
     174        1026 : hexdowncase (char *string)
     175             : {
     176             :   char *p;
     177             : 
     178      132354 :   for (p=string; *p; p++)
     179      131328 :     if (my_isascii (*p))
     180      131328 :       *p = tolower (*p);
     181        1026 : }
     182             : 
     183             : 
     184             : static void
     185        1026 : one_test (int testno, const char *sk, const char *pk,
     186             :           const char *msg, const char *sig)
     187             : {
     188             :   gpg_error_t err;
     189             :   int i;
     190             :   char *p;
     191        1026 :   void *buffer = NULL;
     192        1026 :   void *buffer2 = NULL;
     193             :   size_t buflen, buflen2;
     194             :   gcry_sexp_t s_tmp, s_tmp2;
     195        1026 :   gcry_sexp_t s_sk = NULL;
     196        1026 :   gcry_sexp_t s_pk = NULL;
     197        1026 :   gcry_sexp_t s_msg= NULL;
     198        1026 :   gcry_sexp_t s_sig= NULL;
     199        1026 :   unsigned char *sig_r = NULL;
     200        1026 :   unsigned char *sig_s = NULL;
     201        1026 :   char *sig_rs_string = NULL;
     202             :   size_t sig_r_len, sig_s_len;
     203             : 
     204        1026 :   if (verbose > 1)
     205           0 :     info ("Running test %d\n", testno);
     206             : 
     207        1026 :   if (!(buffer = hex2buffer (sk, &buflen)))
     208             :     {
     209           0 :       fail ("error building s-exp for test %d, %s: %s",
     210             :             testno, "sk", "invalid hex string");
     211           0 :       goto leave;
     212             :     }
     213        1026 :   if (!(buffer2 = hex2buffer (pk, &buflen2)))
     214             :     {
     215           0 :       fail ("error building s-exp for test %d, %s: %s",
     216             :             testno, "pk", "invalid hex string");
     217           0 :       goto leave;
     218             :     }
     219        1026 :   if (sign_with_pk)
     220           0 :     err = gcry_sexp_build (&s_sk, NULL,
     221             :                            "(private-key"
     222             :                            " (ecc"
     223             :                            "  (curve \"Ed25519\")"
     224             :                            "  (flags eddsa)"
     225             :                            "  (q %b)"
     226             :                            "  (d %b)))",
     227             :                            (int)buflen2, buffer2,
     228             :                            (int)buflen, buffer);
     229             :   else
     230        1026 :     err = gcry_sexp_build (&s_sk, NULL,
     231             :                            "(private-key"
     232             :                            " (ecc"
     233             :                            "  (curve \"Ed25519\")"
     234             :                            "  (flags eddsa)"
     235             :                            "  (d %b)))",
     236             :                            (int)buflen, buffer);
     237        1026 :   if (err)
     238             :     {
     239           0 :       fail ("error building s-exp for test %d, %s: %s",
     240             :             testno, "sk", gpg_strerror (err));
     241           0 :       goto leave;
     242             :     }
     243             : 
     244        1026 :   if ((err = gcry_sexp_build (&s_pk, NULL,
     245             :                               "(public-key"
     246             :                               " (ecc"
     247             :                               "  (curve \"Ed25519\")"
     248             :                               "  (flags eddsa)"
     249             :                               "  (q %b)))",  (int)buflen2, buffer2)))
     250             :     {
     251           0 :       fail ("error building s-exp for test %d, %s: %s",
     252             :             testno, "pk", gpg_strerror (err));
     253           0 :       goto leave;
     254             :     }
     255             : 
     256        1026 :   xfree (buffer);
     257        1026 :   if (!(buffer = hex2buffer (msg, &buflen)))
     258             :     {
     259           0 :       fail ("error building s-exp for test %d, %s: %s",
     260             :             testno, "msg", "invalid hex string");
     261           0 :       goto leave;
     262             :     }
     263        1026 :   if ((err = gcry_sexp_build (&s_msg, NULL,
     264             :                               "(data"
     265             :                               " (flags eddsa)"
     266             :                               " (hash-algo sha512)"
     267             :                               " (value %b))",  (int)buflen, buffer)))
     268             :     {
     269           0 :       fail ("error building s-exp for test %d, %s: %s",
     270             :             testno, "msg", gpg_strerror (err));
     271           0 :       goto leave;
     272             :     }
     273             : 
     274        1026 :   if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk)))
     275           0 :     fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err));
     276        1026 :   if (debug)
     277           0 :     show_sexp ("sig=", s_sig);
     278             : 
     279        1026 :   s_tmp2 = NULL;
     280        1026 :   s_tmp = gcry_sexp_find_token (s_sig, "sig-val", 0);
     281        1026 :   if (s_tmp)
     282             :     {
     283        1026 :       s_tmp2 = s_tmp;
     284        1026 :       s_tmp = gcry_sexp_find_token (s_tmp2, "eddsa", 0);
     285        1026 :       if (s_tmp)
     286             :         {
     287        1026 :           gcry_sexp_release (s_tmp2);
     288        1026 :           s_tmp2 = s_tmp;
     289        1026 :           s_tmp = gcry_sexp_find_token (s_tmp2, "r", 0);
     290        1026 :           if (s_tmp)
     291             :             {
     292        1026 :               sig_r = gcry_sexp_nth_buffer (s_tmp, 1, &sig_r_len);
     293        1026 :               gcry_sexp_release (s_tmp);
     294             :             }
     295        1026 :           s_tmp = gcry_sexp_find_token (s_tmp2, "s", 0);
     296        1026 :           if (s_tmp)
     297             :             {
     298        1026 :               sig_s = gcry_sexp_nth_buffer (s_tmp, 1, &sig_s_len);
     299        1026 :               gcry_sexp_release (s_tmp);
     300             :             }
     301             :         }
     302             :     }
     303        1026 :   gcry_sexp_release (s_tmp2); s_tmp2 = NULL;
     304             : 
     305        1026 :   if (!sig_r || !sig_s)
     306           0 :     fail ("gcry_pk_sign failed for test %d: %s", testno, "r or s missing");
     307             :   else
     308             :     {
     309        1026 :       sig_rs_string = xmalloc (2*(sig_r_len + sig_s_len)+1);
     310        1026 :       p = sig_rs_string;
     311        1026 :       *p = 0;
     312       33858 :       for (i=0; i < sig_r_len; i++, p += 2)
     313       32832 :         snprintf (p, 3, "%02x", sig_r[i]);
     314       33858 :       for (i=0; i < sig_s_len; i++, p += 2)
     315       32832 :         snprintf (p, 3, "%02x", sig_s[i]);
     316        1026 :       if (strcmp (sig_rs_string, sig))
     317             :         {
     318           0 :           fail ("gcry_pk_sign failed for test %d: %s",
     319             :                 testno, "wrong value returned");
     320           0 :           info ("  expected: '%s'", sig);
     321           0 :           info ("       got: '%s'", sig_rs_string);
     322             :         }
     323             :     }
     324             : 
     325        1026 :   if (!no_verify)
     326        1026 :     if ((err = gcry_pk_verify (s_sig, s_msg, s_pk)))
     327           0 :       fail ("gcry_pk_verify failed for test %d: %s",
     328             :             testno, gpg_strerror (err));
     329             : 
     330             : 
     331             :  leave:
     332        1026 :   gcry_sexp_release (s_sig);
     333        1026 :   gcry_sexp_release (s_sk);
     334        1026 :   gcry_sexp_release (s_pk);
     335        1026 :   gcry_sexp_release (s_msg);
     336        1026 :   xfree (buffer);
     337        1026 :   xfree (buffer2);
     338        1026 :   xfree (sig_r);
     339        1026 :   xfree (sig_s);
     340        1026 :   xfree (sig_rs_string);
     341        1026 : }
     342             : 
     343             : 
     344             : static void
     345           1 : check_ed25519 (const char *fname)
     346             : {
     347             :   FILE *fp;
     348             :   int lineno, ntests;
     349             :   char *line;
     350             :   int testno;
     351             :   char *sk, *pk, *msg, *sig;
     352             : 
     353           1 :   info ("Checking Ed25519.\n");
     354             : 
     355           1 :   fp = fopen (fname, "r");
     356           1 :   if (!fp)
     357           0 :     die ("error opening '%s': %s\n", fname, strerror (errno));
     358             : 
     359           1 :   testno = 0;
     360           1 :   sk = pk = msg = sig = NULL;
     361           1 :   lineno = ntests = 0;
     362        5132 :   while ((line = read_textline (fp, &lineno)))
     363             :     {
     364        5130 :       if (!strncmp (line, "TST:", 4))
     365        1026 :         testno = atoi (line+4);
     366        4104 :       else if (!strncmp (line, "SK:", 3))
     367        1026 :         copy_data (&sk, line, lineno);
     368        3078 :       else if (!strncmp (line, "PK:", 3))
     369        1026 :         copy_data (&pk, line, lineno);
     370        2052 :       else if (!strncmp (line, "MSG:", 4))
     371        1026 :         copy_data (&msg, line, lineno);
     372        1026 :       else if (!strncmp (line, "SIG:", 4))
     373        1026 :         copy_data (&sig, line, lineno);
     374             :       else
     375           0 :         fail ("unknown tag at input line %d", lineno);
     376             : 
     377        5130 :       xfree (line);
     378        5130 :       if (testno && sk && pk && msg && sig)
     379             :         {
     380        1026 :           hexdowncase (sig);
     381        1026 :           one_test (testno, sk, pk, msg, sig);
     382        1026 :           ntests++;
     383        1026 :           if (!(ntests % 256))
     384           4 :             show_note ("%d of %d tests done\n", ntests, N_TESTS);
     385        1026 :           xfree (pk);  pk = NULL;
     386        1026 :           xfree (sk);  sk = NULL;
     387        1026 :           xfree (msg); msg = NULL;
     388        1026 :           xfree (sig); sig = NULL;
     389             :         }
     390             : 
     391             :     }
     392           1 :   xfree (pk);
     393           1 :   xfree (sk);
     394           1 :   xfree (msg);
     395           1 :   xfree (sig);
     396             : 
     397           1 :   if (ntests != N_TESTS && !custom_data_file)
     398           0 :     fail ("did %d tests but expected %d", ntests, N_TESTS);
     399           1 :   else if ((ntests % 256))
     400           1 :     show_note ("%d tests done\n", ntests);
     401             : 
     402           1 :   fclose (fp);
     403           1 : }
     404             : 
     405             : 
     406             : int
     407           1 : main (int argc, char **argv)
     408             : {
     409           1 :   int last_argc = -1;
     410           1 :   char *fname = NULL;
     411             : 
     412           1 :   if (argc)
     413           1 :     { argc--; argv++; }
     414             : 
     415           2 :   while (argc && last_argc != argc )
     416             :     {
     417           0 :       last_argc = argc;
     418           0 :       if (!strcmp (*argv, "--"))
     419             :         {
     420           0 :           argc--; argv++;
     421           0 :           break;
     422             :         }
     423           0 :       else if (!strcmp (*argv, "--help"))
     424             :         {
     425           0 :           fputs ("usage: " PGM " [options]\n"
     426             :                  "Options:\n"
     427             :                  "  --verbose       print timings etc.\n"
     428             :                  "  --debug         flyswatter\n"
     429             :                  "  --sign-with-pk  also use the public key for signing\n"
     430             :                  "  --no-verify     skip the verify test\n"
     431             :                  "  --data FNAME    take test data from file FNAME\n",
     432             :                  stdout);
     433           0 :           exit (0);
     434             :         }
     435           0 :       else if (!strcmp (*argv, "--verbose"))
     436             :         {
     437           0 :           verbose++;
     438           0 :           argc--; argv++;
     439             :         }
     440           0 :       else if (!strcmp (*argv, "--debug"))
     441             :         {
     442           0 :           verbose += 2;
     443           0 :           debug++;
     444           0 :           argc--; argv++;
     445             :         }
     446           0 :       else if (!strcmp (*argv, "--sign-with-pk"))
     447             :         {
     448           0 :           sign_with_pk = 1;
     449           0 :           argc--; argv++;
     450             :         }
     451           0 :       else if (!strcmp (*argv, "--no-verify"))
     452             :         {
     453           0 :           no_verify = 1;
     454           0 :           argc--; argv++;
     455             :         }
     456           0 :       else if (!strcmp (*argv, "--data"))
     457             :         {
     458           0 :           argc--; argv++;
     459           0 :           if (argc)
     460             :             {
     461           0 :               xfree (fname);
     462           0 :               fname = xstrdup (*argv);
     463           0 :               argc--; argv++;
     464             :             }
     465             :         }
     466           0 :       else if (!strncmp (*argv, "--", 2))
     467           0 :         die ("unknown option '%s'", *argv);
     468             : 
     469             :     }
     470             : 
     471           1 :   if (!fname)
     472           1 :     fname = prepend_srcdir ("t-ed25519.inp");
     473             :   else
     474           0 :     custom_data_file = 1;
     475             : 
     476           1 :   xgcry_control (GCRYCTL_DISABLE_SECMEM, 0);
     477           1 :   if (!gcry_check_version (GCRYPT_VERSION))
     478           0 :     die ("version mismatch\n");
     479           1 :   if (debug)
     480           0 :     xgcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0);
     481           1 :   xgcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
     482           1 :   xgcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
     483             : 
     484             :   /* Ed25519 isn't supported in fips mode */
     485           1 :   if (gcry_fips_mode_active())
     486           0 :     return 77;
     487             : 
     488           1 :   start_timer ();
     489           1 :   check_ed25519 (fname);
     490           1 :   stop_timer ();
     491             : 
     492           1 :   xfree (fname);
     493             : 
     494           1 :   info ("All tests completed in %s.  Errors: %d\n",
     495             :         elapsed_time (1), error_count);
     496           1 :   return !!error_count;
     497             : }

Generated by: LCOV version 1.12