LCOV - code coverage report
Current view: top level - tests - random.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 162 341 47.5 %
Date: 2016-12-01 18:32:04 Functions: 8 15 53.3 %

          Line data    Source code
       1             : /* random.c - part of the Libgcrypt test suite.
       2             :    Copyright (C) 2005 Free Software Foundation, Inc.
       3             : 
       4             :    This program is free software; you can redistribute it and/or
       5             :    modify it under the terms of the GNU General Public License as
       6             :    published by the Free Software Foundation; either version 2 of the
       7             :    License, or (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful, but
      10             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             :    General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program; if not, write to the Free Software
      16             :    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      17             :    USA.  */
      18             : 
      19             : #ifdef HAVE_CONFIG_H
      20             : #include <config.h>
      21             : #endif
      22             : #include <assert.h>
      23             : #include <stdio.h>
      24             : #include <string.h>
      25             : #include <stdlib.h>
      26             : #include <errno.h>
      27             : #ifndef HAVE_W32_SYSTEM
      28             : # include <signal.h>
      29             : # include <unistd.h>
      30             : # include <sys/wait.h>
      31             : #endif
      32             : 
      33             : #include "../src/gcrypt-int.h"
      34             : 
      35             : #define PGM "random"
      36             : 
      37             : #ifndef DIM
      38             : # define DIM(v)              (sizeof(v)/sizeof((v)[0]))
      39             : #endif
      40             : 
      41             : 
      42             : static int verbose;
      43             : static int debug;
      44             : static int with_progress;
      45             : 
      46             : /* If we have a decent libgpg-error we can use some gcc attributes.  */
      47             : #ifdef GPGRT_ATTR_NORETURN
      48             : static void die (const char *format, ...) GPGRT_ATTR_NR_PRINTF(1,2);
      49             : static void inf (const char *format, ...) GPGRT_ATTR_PRINTF(1,2);
      50             : #endif /*GPGRT_ATTR_NORETURN*/
      51             : 
      52             : 
      53             : static void
      54           0 : die (const char *format, ...)
      55             : {
      56             :   va_list arg_ptr;
      57             : 
      58           0 :   va_start (arg_ptr, format);
      59           0 :   fputs ( PGM ": ", stderr);
      60           0 :   vfprintf (stderr, format, arg_ptr);
      61           0 :   va_end (arg_ptr);
      62           0 :   exit (1);
      63             : }
      64             : 
      65             : 
      66             : static void
      67           0 : inf (const char *format, ...)
      68             : {
      69             :   va_list arg_ptr;
      70             : 
      71           0 :   va_start (arg_ptr, format);
      72           0 :   fputs ( PGM ": ", stderr);
      73           0 :   vfprintf (stderr, format, arg_ptr);
      74           0 :   va_end (arg_ptr);
      75           0 : }
      76             : 
      77             : 
      78             : static void
      79           0 : print_hex (const char *text, const void *buf, size_t n)
      80             : {
      81           0 :   const unsigned char *p = buf;
      82             : 
      83           0 :   inf ("%s", text);
      84           0 :   for (; n; n--, p++)
      85           0 :     fprintf (stderr, "%02X", *p);
      86           0 :   putc ('\n', stderr);
      87           0 : }
      88             : 
      89             : 
      90             : static void
      91           0 : progress_cb (void *cb_data, const char *what, int printchar,
      92             :              int current, int total)
      93             : {
      94             :   (void)cb_data;
      95             : 
      96           0 :   inf ("progress (%s %c %d %d)\n", what, printchar, current, total);
      97           0 :   fflush (stderr);
      98           0 : }
      99             : 
     100             : 
     101             : #ifndef HAVE_W32_SYSTEM
     102             : static int
     103           0 : writen (int fd, const void *buf, size_t nbytes)
     104             : {
     105           0 :   size_t nleft = nbytes;
     106             :   int nwritten;
     107             : 
     108           0 :   while (nleft > 0)
     109             :     {
     110           0 :       nwritten = write (fd, buf, nleft);
     111           0 :       if (nwritten < 0)
     112             :         {
     113           0 :           if (errno == EINTR)
     114           0 :             nwritten = 0;
     115             :           else
     116           0 :             return -1;
     117             :         }
     118           0 :       nleft -= nwritten;
     119           0 :       buf = (const char*)buf + nwritten;
     120             :     }
     121             : 
     122           0 :   return 0;
     123             : }
     124             : #endif /*!HAVE_W32_SYSTEM*/
     125             : 
     126             : 
     127             : #ifndef HAVE_W32_SYSTEM
     128             : static int
     129           2 : readn (int fd, void *buf, size_t buflen, size_t *ret_nread)
     130             : {
     131           2 :   size_t nleft = buflen;
     132             :   int nread;
     133             : 
     134           6 :   while ( nleft > 0 )
     135             :     {
     136           2 :       nread = read ( fd, buf, nleft );
     137           2 :       if (nread < 0)
     138             :         {
     139           0 :           if (nread == EINTR)
     140           0 :             nread = 0;
     141             :           else
     142           0 :             return -1;
     143             :         }
     144           2 :       else if (!nread)
     145           0 :         break; /* EOF */
     146           2 :       nleft -= nread;
     147           2 :       buf = (char*)buf + nread;
     148             :     }
     149           2 :   if (ret_nread)
     150           2 :     *ret_nread = buflen - nleft;
     151           2 :   return 0;
     152             : }
     153             : #endif /*!HAVE_W32_SYSTEM*/
     154             : 
     155             : 
     156             : /* Check that forking won't return the same random. */
     157             : static void
     158           1 : check_forking (void)
     159             : {
     160             : #ifdef HAVE_W32_SYSTEM
     161             :   if (verbose)
     162             :     inf ("check_forking skipped: not applicable on Windows\n");
     163             : #else /*!HAVE_W32_SYSTEM*/
     164             :   pid_t pid;
     165             :   int rp[2];
     166             :   int i, status;
     167             :   size_t nread;
     168             :   char tmp1[16], tmp1c[16], tmp1p[16];
     169             : 
     170           1 :   if (verbose)
     171           0 :     inf ("checking that a fork won't cause the same random output\n");
     172             : 
     173             :   /* We better make sure that the RNG has been initialzied. */
     174           1 :   gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM);
     175           1 :   if (verbose)
     176           0 :     print_hex ("initial random: ", tmp1, sizeof tmp1);
     177             : 
     178           1 :   if (pipe (rp) == -1)
     179           0 :     die ("pipe failed: %s\n", strerror (errno));
     180             : 
     181           1 :   pid = fork ();
     182           1 :   if (pid == (pid_t)(-1))
     183           0 :     die ("fork failed: %s\n", strerror (errno));
     184           1 :   if (!pid)
     185             :     {
     186           0 :       gcry_randomize (tmp1c, sizeof tmp1c, GCRY_STRONG_RANDOM);
     187           0 :       if (writen (rp[1], tmp1c, sizeof tmp1c))
     188           0 :         die ("write failed: %s\n", strerror (errno));
     189           0 :       if (verbose)
     190             :         {
     191           0 :           print_hex ("  child random: ", tmp1c, sizeof tmp1c);
     192           0 :           fflush (stdout);
     193             :         }
     194           0 :       _exit (0);
     195             :     }
     196           1 :   gcry_randomize (tmp1p, sizeof tmp1p, GCRY_STRONG_RANDOM);
     197           1 :   if (verbose)
     198           0 :     print_hex (" parent random: ", tmp1p, sizeof tmp1p);
     199             : 
     200           1 :   close (rp[1]);
     201           1 :   if (readn (rp[0], tmp1c, sizeof tmp1c, &nread))
     202           0 :     die ("read failed: %s\n", strerror (errno));
     203           1 :   if (nread != sizeof tmp1c)
     204           0 :     die ("read too short\n");
     205             : 
     206           1 :   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
     207             :     ;
     208           1 :   if (i != (pid_t)(-1)
     209           1 :       && WIFEXITED (status) && !WEXITSTATUS (status))
     210             :     ;
     211             :   else
     212           0 :     die ("child failed\n");
     213             : 
     214           1 :   if (!memcmp (tmp1p, tmp1c, sizeof tmp1c))
     215           0 :     die ("parent and child got the same random number\n");
     216             : #endif  /*!HAVE_W32_SYSTEM*/
     217           1 : }
     218             : 
     219             : 
     220             : 
     221             : /* Check that forking won't return the same nonce. */
     222             : static void
     223           1 : check_nonce_forking (void)
     224             : {
     225             : #ifdef HAVE_W32_SYSTEM
     226             :   if (verbose)
     227             :     inf ("check_nonce_forking skipped: not applicable on Windows\n");
     228             : #else /*!HAVE_W32_SYSTEM*/
     229             :   pid_t pid;
     230             :   int rp[2];
     231             :   int i, status;
     232             :   size_t nread;
     233             :   char nonce1[10], nonce1c[10], nonce1p[10];
     234             : 
     235           1 :   if (verbose)
     236           0 :     inf ("checking that a fork won't cause the same nonce output\n");
     237             : 
     238             :   /* We won't get the same nonce back if we never initialized the
     239             :      nonce subsystem, thus we get one nonce here and forget about
     240             :      it. */
     241           1 :   gcry_create_nonce (nonce1, sizeof nonce1);
     242           1 :   if (verbose)
     243           0 :     print_hex ("initial nonce: ", nonce1, sizeof nonce1);
     244             : 
     245           1 :   if (pipe (rp) == -1)
     246           0 :     die ("pipe failed: %s\n", strerror (errno));
     247             : 
     248           1 :   pid = fork ();
     249           1 :   if (pid == (pid_t)(-1))
     250           0 :     die ("fork failed: %s\n", strerror (errno));
     251           1 :   if (!pid)
     252             :     {
     253           0 :       gcry_create_nonce (nonce1c, sizeof nonce1c);
     254           0 :       if (writen (rp[1], nonce1c, sizeof nonce1c))
     255           0 :         die ("write failed: %s\n", strerror (errno));
     256           0 :       if (verbose)
     257             :         {
     258           0 :           print_hex ("  child nonce: ", nonce1c, sizeof nonce1c);
     259           0 :           fflush (stdout);
     260             :         }
     261           0 :       _exit (0);
     262             :     }
     263           1 :   gcry_create_nonce (nonce1p, sizeof nonce1p);
     264           1 :   if (verbose)
     265           0 :     print_hex (" parent nonce: ", nonce1p, sizeof nonce1p);
     266             : 
     267           1 :   close (rp[1]);
     268           1 :   if (readn (rp[0], nonce1c, sizeof nonce1c, &nread))
     269           0 :     die ("read failed: %s\n", strerror (errno));
     270           1 :   if (nread != sizeof nonce1c)
     271           0 :     die ("read too short\n");
     272             : 
     273           1 :   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
     274             :     ;
     275           1 :   if (i != (pid_t)(-1)
     276           1 :       && WIFEXITED (status) && !WEXITSTATUS (status))
     277             :     ;
     278             :   else
     279           0 :     die ("child failed\n");
     280             : 
     281           1 :   if (!memcmp (nonce1p, nonce1c, sizeof nonce1c))
     282           0 :     die ("parent and child got the same nonce\n");
     283             : #endif  /*!HAVE_W32_SYSTEM*/
     284           1 : }
     285             : 
     286             : 
     287             : /* Check that a closed random device os re-opened if needed. */
     288             : static void
     289           1 : check_close_random_device (void)
     290             : {
     291             : #ifdef HAVE_W32_SYSTEM
     292             :   if (verbose)
     293             :     inf ("check_close_random_device skipped: not applicable on Windows\n");
     294             : #else /*!HAVE_W32_SYSTEM*/
     295             :   pid_t pid;
     296             :   int i, status;
     297             :   char buf[4];
     298             : 
     299           1 :   if (verbose)
     300           0 :     inf ("checking that close_random_device works\n");
     301             : 
     302           1 :   gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM);
     303           1 :   if (verbose)
     304           0 :     print_hex ("parent random: ", buf, sizeof buf);
     305             : 
     306           1 :   pid = fork ();
     307           1 :   if (pid == (pid_t)(-1))
     308           0 :     die ("fork failed: %s\n", strerror (errno));
     309           1 :   if (!pid)
     310             :     {
     311           0 :       gcry_control (GCRYCTL_CLOSE_RANDOM_DEVICE, 0);
     312             : 
     313             :       /* The next call will re-open the device.  */
     314           0 :       gcry_randomize (buf, sizeof buf, GCRY_STRONG_RANDOM);
     315           0 :       if (verbose)
     316             :         {
     317           0 :           print_hex ("child random : ", buf, sizeof buf);
     318           0 :           fflush (stdout);
     319             :         }
     320           0 :       _exit (0);
     321             :     }
     322             : 
     323           1 :   while ( (i=waitpid (pid, &status, 0)) == -1 && errno == EINTR)
     324             :     ;
     325           1 :   if (i != (pid_t)(-1)
     326           1 :       && WIFEXITED (status) && !WEXITSTATUS (status))
     327             :     ;
     328             :   else
     329           0 :     die ("child failed\n");
     330             : 
     331             : #endif  /*!HAVE_W32_SYSTEM*/
     332           1 : }
     333             : 
     334             : 
     335             : static int
     336          64 : rng_type (void)
     337             : {
     338             :   int rngtype;
     339          64 :   if (gcry_control (GCRYCTL_GET_CURRENT_RNG_TYPE, &rngtype))
     340           0 :     die ("retrieving RNG type failed\n");
     341          64 :   return rngtype;
     342             : }
     343             : 
     344             : 
     345             : static void
     346           8 : check_rng_type_switching (void)
     347             : {
     348             :   int rngtype, initial;
     349             :   char tmp1[4];
     350             : 
     351           8 :   if (verbose)
     352           0 :     inf ("checking whether RNG type switching works\n");
     353             : 
     354           8 :   rngtype = rng_type ();
     355           8 :   if (debug)
     356           0 :     inf ("rng type: %d\n", rngtype);
     357           8 :   initial = rngtype;
     358           8 :   gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM);
     359           8 :   if (debug)
     360           0 :     print_hex ("  sample: ", tmp1, sizeof tmp1);
     361           8 :   if (rngtype != rng_type ())
     362           0 :     die ("RNG type unexpectedly changed\n");
     363             : 
     364           8 :   gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
     365             : 
     366           8 :   rngtype = rng_type ();
     367           8 :   if (debug)
     368           0 :     inf ("rng type: %d\n", rngtype);
     369           8 :   if (rngtype != initial)
     370           0 :     die ("switching to System RNG unexpectedly succeeded\n");
     371           8 :   gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM);
     372           8 :   if (debug)
     373           0 :     print_hex ("  sample: ", tmp1, sizeof tmp1);
     374           8 :   if (rngtype != rng_type ())
     375           0 :     die ("RNG type unexpectedly changed\n");
     376             : 
     377           8 :   gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
     378             : 
     379           8 :   rngtype = rng_type ();
     380           8 :   if (debug)
     381           0 :     inf ("rng type: %d\n", rngtype);
     382           8 :   if (rngtype != initial)
     383           0 :     die ("switching to FIPS RNG unexpectedly succeeded\n");
     384           8 :   gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM);
     385           8 :   if (debug)
     386           0 :     print_hex ("  sample: ", tmp1, sizeof tmp1);
     387           8 :   if (rngtype != rng_type ())
     388           0 :     die ("RNG type unexpectedly changed\n");
     389             : 
     390           8 :   gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD);
     391             : 
     392           8 :   rngtype = rng_type ();
     393           8 :   if (debug)
     394           0 :     inf ("rng type: %d\n", rngtype);
     395           8 :   if (rngtype != GCRY_RNG_TYPE_STANDARD)
     396           0 :     die ("switching to standard RNG failed\n");
     397           8 :   gcry_randomize (tmp1, sizeof tmp1, GCRY_STRONG_RANDOM);
     398           8 :   if (debug)
     399           0 :     print_hex ("  sample: ", tmp1, sizeof tmp1);
     400           8 :   if (rngtype != rng_type ())
     401           0 :     die ("RNG type unexpectedly changed\n");
     402           8 : }
     403             : 
     404             : 
     405             : static void
     406           0 : check_early_rng_type_switching (void)
     407             : {
     408             :   int rngtype, initial;
     409             : 
     410           0 :   if (verbose)
     411           0 :     inf ("checking whether RNG type switching works in the early stage\n");
     412             : 
     413           0 :   rngtype = rng_type ();
     414           0 :   if (debug)
     415           0 :     inf ("rng type: %d\n", rngtype);
     416           0 :   initial = rngtype;
     417             : 
     418           0 :   gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
     419             : 
     420           0 :   rngtype = rng_type ();
     421           0 :   if (debug)
     422           0 :     inf ("rng type: %d\n", rngtype);
     423           0 :   if (initial >= GCRY_RNG_TYPE_SYSTEM && rngtype != GCRY_RNG_TYPE_SYSTEM)
     424           0 :     die ("switching to System RNG failed\n");
     425             : 
     426           0 :   gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
     427             : 
     428           0 :   rngtype = rng_type ();
     429           0 :   if (debug)
     430           0 :     inf ("rng type: %d\n", rngtype);
     431           0 :   if (initial >= GCRY_RNG_TYPE_FIPS && rngtype != GCRY_RNG_TYPE_FIPS)
     432           0 :     die ("switching to FIPS RNG failed\n");
     433             : 
     434           0 :   gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD);
     435             : 
     436           0 :   rngtype = rng_type ();
     437           0 :   if (debug)
     438           0 :     inf ("rng type: %d\n", rngtype);
     439           0 :   if (rngtype != GCRY_RNG_TYPE_STANDARD)
     440           0 :     die ("switching to standard RNG failed\n");
     441           0 : }
     442             : 
     443             : 
     444             : static void
     445           0 : check_drbg_reinit (void)
     446             : {
     447             :   static struct { const char *flags; } tv[] = {
     448             :     { NULL },
     449             :     { "" },
     450             :     { "sha1" },
     451             :     { "sha1 pr" },
     452             :     { "sha256" },
     453             :     { "sha256 pr" },
     454             :     { "sha512" },
     455             :     { "sha512 pr" },
     456             :     { "hmac sha1" },
     457             :     { "hmac sha1 pr" },
     458             :     { "hmac sha256" },
     459             :     { "hmac sha256 pr" },
     460             :     { "hmac sha512" },
     461             :     { "hmac sha512 pr" },
     462             :     { "aes sym128" },
     463             :     { "aes sym128 pr" },
     464             :     { "aes sym192" },
     465             :     { "aes sym192 pr" },
     466             :     { "aes sym256" },
     467             :     { "aes sym256 pr" }
     468             :   };
     469             :   int tidx;
     470             :   gpg_error_t err;
     471           0 :   char pers_string[] = "I'm a doctor, not an engineer.";
     472             :   gcry_buffer_t pers[1];
     473             : 
     474           0 :   if (verbose)
     475           0 :     inf ("checking DRBG_REINIT\n");
     476             : 
     477           0 :   memset (pers, 0, sizeof pers);
     478           0 :   pers[0].data = pers_string;
     479           0 :   pers[0].len = strlen (pers_string);
     480             : 
     481           0 :   err = gcry_control (GCRYCTL_DRBG_REINIT, "", NULL, 0, &err);
     482           0 :   if (gpg_err_code (err) != GPG_ERR_INV_ARG)
     483           0 :     die ("gcry_control(DRBG_REINIT) guard value did not work\n");
     484             : 
     485           0 :   err = gcry_control (GCRYCTL_DRBG_REINIT, "", NULL, -1, NULL);
     486           0 :   if (gpg_err_code (err) != GPG_ERR_INV_ARG)
     487           0 :     die ("gcry_control(DRBG_REINIT) npers negative detection failed\n");
     488             : 
     489           0 :   if (rng_type () != GCRY_RNG_TYPE_FIPS)
     490             :     {
     491           0 :       err = gcry_control (GCRYCTL_DRBG_REINIT, "", NULL, 0, NULL);
     492           0 :       if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED)
     493           0 :         die ("DRBG_REINIT worked despite that DRBG is not active\n");
     494           0 :       return;
     495             :     }
     496             : 
     497           0 :   err = gcry_control (GCRYCTL_DRBG_REINIT, "", NULL, 1, NULL);
     498           0 :   if (gpg_err_code (err) != GPG_ERR_INV_ARG)
     499           0 :     die ("_gcry_rngdrbg_reinit failed to detact: (!pers && npers)\n");
     500           0 :   err = gcry_control (GCRYCTL_DRBG_REINIT, "", pers, 2, NULL);
     501           0 :   if (gpg_err_code (err) != GPG_ERR_INV_ARG)
     502           0 :     die ("_gcry_rngdrbg_reinit failed to detect: (pers && npers != 1)\n");
     503             : 
     504           0 :   err = gcry_control (GCRYCTL_DRBG_REINIT, "aes sym128 bad pr ", pers, 1, NULL);
     505           0 :   if (gpg_err_code (err) != GPG_ERR_INV_FLAG)
     506           0 :     die ("_gcry_rngdrbg_reinit failed to detect a bad flag\n");
     507             : 
     508           0 :   for (tidx=0; tidx < DIM(tv); tidx++)
     509             :     {
     510           0 :       err = gcry_control (GCRYCTL_DRBG_REINIT, tv[tidx].flags, NULL, 0, NULL);
     511           0 :       if (err)
     512           0 :         die ("_gcry_rngdrbg_reinit failed for \"%s\" w/o pers: %s\n",
     513             : 
     514             :              tv[tidx].flags, gpg_strerror (err));
     515           0 :       err = gcry_control (GCRYCTL_DRBG_REINIT, tv[tidx].flags, pers, 1, NULL);
     516           0 :       if (err)
     517           0 :         die ("_gcry_rngdrbg_reinit failed for \"%s\" with pers: %s\n",
     518             :              tv[tidx].flags, gpg_strerror (err));
     519             :       /* fixme: We should extract some random after each test.  */
     520             :     }
     521             : }
     522             : 
     523             : 
     524             : /* Because we want to check initialization behaviour, we need to
     525             :    fork/exec this program with several command line arguments.  We use
     526             :    system, so that these tests work also on Windows.  */
     527             : static void
     528           1 : run_all_rng_tests (const char *program)
     529             : {
     530             :   static const char *options[] = {
     531             :     "--early-rng-check",
     532             :     "--early-rng-check --prefer-standard-rng",
     533             :     "--early-rng-check --prefer-fips-rng",
     534             :     "--early-rng-check --prefer-system-rng",
     535             :     "--prefer-standard-rng",
     536             :     "--prefer-fips-rng",
     537             :     "--prefer-system-rng",
     538             :     NULL
     539             :   };
     540             :   int idx;
     541             :   size_t len, maxlen;
     542             :   char *cmdline;
     543             : 
     544           1 :   maxlen = 0;
     545           8 :   for (idx=0; options[idx]; idx++)
     546             :     {
     547           7 :       len = strlen (options[idx]);
     548           7 :       if (len > maxlen)
     549           2 :         maxlen = len;
     550             :     }
     551           1 :   maxlen += strlen (program);
     552           1 :   maxlen += strlen (" --in-recursion --verbose --debug --progress");
     553           1 :   maxlen++;
     554           1 :   cmdline = malloc (maxlen + 1);
     555           1 :   if (!cmdline)
     556           0 :     die ("out of core\n");
     557             : 
     558           8 :   for (idx=0; options[idx]; idx++)
     559             :     {
     560           7 :       if (verbose)
     561           0 :         inf ("now running with options '%s'\n", options[idx]);
     562           7 :       strcpy (cmdline, program);
     563           7 :       strcat (cmdline, " --in-recursion");
     564           7 :       if (verbose)
     565           0 :         strcat (cmdline, " --verbose");
     566           7 :       if (debug)
     567           0 :         strcat (cmdline, " --debug");
     568           7 :       if (with_progress)
     569           0 :         strcat (cmdline, " --progress");
     570           7 :       strcat (cmdline, " ");
     571           7 :       strcat (cmdline, options[idx]);
     572           7 :       if (system (cmdline))
     573           0 :         die ("running '%s' failed\n", cmdline);
     574             :     }
     575             : 
     576           1 :   free (cmdline);
     577           1 : }
     578             : 
     579             : int
     580           8 : main (int argc, char **argv)
     581             : {
     582           8 :   int last_argc = -1;
     583           8 :   int early_rng = 0;
     584           8 :   int in_recursion = 0;
     585           8 :   const char *program = NULL;
     586             : 
     587           8 :   if (argc)
     588             :     {
     589           8 :       program = *argv;
     590           8 :       argc--; argv++;
     591             :     }
     592             :   else
     593           0 :     die ("argv[0] missing\n");
     594             : 
     595          33 :   while (argc && last_argc != argc )
     596             :     {
     597          17 :       last_argc = argc;
     598          17 :       if (!strcmp (*argv, "--"))
     599             :         {
     600           0 :           argc--; argv++;
     601           0 :           break;
     602             :         }
     603          17 :       else if (!strcmp (*argv, "--help"))
     604             :         {
     605           0 :           fputs ("usage: random [options]\n", stdout);
     606           0 :           exit (0);
     607             :         }
     608          17 :       else if (!strcmp (*argv, "--verbose"))
     609             :         {
     610           0 :           verbose = 1;
     611           0 :           argc--; argv++;
     612             :         }
     613          17 :       else if (!strcmp (*argv, "--debug"))
     614             :         {
     615           0 :           debug = verbose = 1;
     616           0 :           argc--; argv++;
     617             :         }
     618          17 :       else if (!strcmp (*argv, "--progress"))
     619             :         {
     620           0 :           argc--; argv++;
     621           0 :           with_progress = 1;
     622             :         }
     623          17 :       else if (!strcmp (*argv, "--in-recursion"))
     624             :         {
     625           7 :           in_recursion = 1;
     626           7 :           argc--; argv++;
     627             :         }
     628          10 :       else if (!strcmp (*argv, "--early-rng-check"))
     629             :         {
     630           4 :           early_rng = 1;
     631           4 :           argc--; argv++;
     632             :         }
     633           6 :       else if (!strcmp (*argv, "--prefer-standard-rng"))
     634             :         {
     635             :           /* This is anyway the default, but we may want to use it for
     636             :              debugging. */
     637           2 :           gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_STANDARD);
     638           2 :           argc--; argv++;
     639             :         }
     640           4 :       else if (!strcmp (*argv, "--prefer-fips-rng"))
     641             :         {
     642           2 :           gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_FIPS);
     643           2 :           argc--; argv++;
     644             :         }
     645           2 :       else if (!strcmp (*argv, "--prefer-system-rng"))
     646             :         {
     647           2 :           gcry_control (GCRYCTL_SET_PREFERRED_RNG_TYPE, GCRY_RNG_TYPE_SYSTEM);
     648           2 :           argc--; argv++;
     649             :         }
     650             :     }
     651             : 
     652             : #ifndef HAVE_W32_SYSTEM
     653           8 :   signal (SIGPIPE, SIG_IGN);
     654             : #endif
     655             : 
     656           8 :   if (early_rng)
     657             :     {
     658             :       /* Don't switch RNG in fips mode. */
     659           4 :       if (!gcry_fips_mode_active())
     660           0 :         check_early_rng_type_switching ();
     661             :     }
     662             : 
     663           8 :   gcry_control (GCRYCTL_DISABLE_SECMEM, 0);
     664           8 :   if (!gcry_check_version (GCRYPT_VERSION))
     665           0 :     die ("version mismatch\n");
     666             : 
     667           8 :   if (with_progress)
     668           0 :     gcry_set_progress_handler (progress_cb, NULL);
     669             : 
     670           8 :   gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
     671           8 :   if (debug)
     672           0 :     gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u, 0);
     673             : 
     674           8 :   if (!in_recursion)
     675             :     {
     676           1 :       check_forking ();
     677           1 :       check_nonce_forking ();
     678           1 :       check_close_random_device ();
     679             :     }
     680             :   /* For now we do not run the drgb_reinit check from "make check" due
     681             :      to its high requirement for entropy.  */
     682           8 :   if (!getenv ("GCRYPT_IN_REGRESSION_TEST"))
     683           0 :     check_drbg_reinit ();
     684             : 
     685             :   /* Don't switch RNG in fips mode.  */
     686           8 :   if (!gcry_fips_mode_active())
     687           8 :     check_rng_type_switching ();
     688             : 
     689           8 :   if (!in_recursion)
     690           1 :     run_all_rng_tests (program);
     691             : 
     692           8 :   return 0;
     693             : }

Generated by: LCOV version 1.11