LCOV - code coverage report
Current view: top level - util - test_helper_cs.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 78.4 % 417 327
Test Date: 2026-01-04 22:17:00 Functions: 100.0 % 10 10

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   (C) 2020, 2021, 2023 Taler Systems SA
       4              : 
       5              :   TALER is free software; you can redistribute it and/or modify it under the
       6              :   terms of the GNU General Public License as published by the Free Software
       7              :   Foundation; either version 3, or (at your option) any later version.
       8              : 
       9              :   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      10              :   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11              :   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      12              : 
      13              :   You should have received a copy of the GNU General Public License along with
      14              :   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15              : */
      16              : /**
      17              :  * @file util/test_helper_cs.c
      18              :  * @brief Tests for CS crypto helper
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "taler/platform.h"
      22              : #include "taler/taler_util.h"
      23              : 
      24              : /**
      25              :  * Configuration has 1 minute duration and 5 minutes lookahead, but
      26              :  * we do not get 'revocations' for expired keys. So this must be
      27              :  * large enough to deal with key rotation during the runtime of
      28              :  * the benchmark.
      29              :  */
      30              : #define MAX_KEYS 1024
      31              : 
      32              : /**
      33              :  * How many random key revocations should we test?
      34              :  */
      35              : #define NUM_REVOKES 3
      36              : 
      37              : /**
      38              :  * How many iterations of the successful signing test should we run?
      39              :  */
      40              : #define NUM_SIGN_TESTS 5
      41              : 
      42              : /**
      43              :  * How many iterations of the successful signing test should we run
      44              :  * during the benchmark phase?
      45              :  */
      46              : #define NUM_SIGN_PERFS 100
      47              : 
      48              : /**
      49              :  * How many parallel clients should we use for the parallel
      50              :  * benchmark? (> 500 may cause problems with the max open FD number limit).
      51              :  */
      52              : #define NUM_CORES 8
      53              : 
      54              : /**
      55              :  * Number of keys currently in #keys.
      56              :  */
      57              : static unsigned int num_keys;
      58              : 
      59              : /**
      60              :  * Keys currently managed by the helper.
      61              :  */
      62              : struct KeyData
      63              : {
      64              :   /**
      65              :    * Validity start point.
      66              :    */
      67              :   struct GNUNET_TIME_Timestamp start_time;
      68              : 
      69              :   /**
      70              :    * Key expires for signing at @e start_time plus this value.
      71              :    */
      72              :   struct GNUNET_TIME_Relative validity_duration;
      73              : 
      74              :   /**
      75              :    * Hash of the public key.
      76              :    */
      77              :   struct TALER_CsPubHashP h_cs;
      78              : 
      79              :   /**
      80              :    * Full public key.
      81              :    */
      82              :   struct TALER_DenominationPublicKey denom_pub;
      83              : 
      84              :   /**
      85              :    * Is this key currently valid?
      86              :    */
      87              :   bool valid;
      88              : 
      89              :   /**
      90              :    * Did the test driver revoke this key?
      91              :    */
      92              :   bool revoked;
      93              : };
      94              : 
      95              : /**
      96              :  * Array of all the keys we got from the helper.
      97              :  */
      98              : static struct KeyData keys[MAX_KEYS];
      99              : 
     100              : 
     101              : /**
     102              :  * Release memory occupied by #keys.
     103              :  */
     104              : static void
     105            9 : free_keys (void)
     106              : {
     107         9225 :   for (unsigned int i = 0; i<MAX_KEYS; i++)
     108         9216 :     if (keys[i].valid)
     109              :     {
     110           78 :       TALER_denom_pub_free (&keys[i].denom_pub);
     111           78 :       keys[i].valid = false;
     112           78 :       GNUNET_assert (num_keys > 0);
     113           78 :       num_keys--;
     114              :     }
     115            9 : }
     116              : 
     117              : 
     118              : /**
     119              :  * Function called with information about available keys for signing.  Usually
     120              :  * only called once per key upon connect. Also called again in case a key is
     121              :  * being revoked, in that case with an @a end_time of zero.  Stores the keys
     122              :  * status in #keys.
     123              :  *
     124              :  * @param cls closure, NULL
     125              :  * @param section_name name of the denomination type in the configuration;
     126              :  *                 NULL if the key has been revoked or purged
     127              :  * @param start_time when does the key become available for signing;
     128              :  *                 zero if the key has been revoked or purged
     129              :  * @param validity_duration how long does the key remain available for signing;
     130              :  *                 zero if the key has been revoked or purged
     131              :  * @param h_cs hash of the @a denom_pub that is available (or was purged)
     132              :  * @param bs_pub the public key itself, NULL if the key was revoked or purged
     133              :  * @param sm_pub public key of the security module, NULL if the key was revoked or purged
     134              :  * @param sm_sig signature from the security module, NULL if the key was revoked or purged
     135              :  *               The signature was already verified against @a sm_pub.
     136              :  */
     137              : static void
     138           84 : key_cb (void *cls,
     139              :         const char *section_name,
     140              :         struct GNUNET_TIME_Timestamp start_time,
     141              :         struct GNUNET_TIME_Relative validity_duration,
     142              :         const struct TALER_CsPubHashP *h_cs,
     143              :         struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
     144              :         const struct TALER_SecurityModulePublicKeyP *sm_pub,
     145              :         const struct TALER_SecurityModuleSignatureP *sm_sig)
     146              : {
     147              :   (void) cls;
     148              :   (void) sm_pub;
     149              :   (void) sm_sig;
     150           84 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     151              :               "Key notification about key %s in `%s'\n",
     152              :               GNUNET_h2s (&h_cs->hash),
     153              :               section_name);
     154           84 :   if (0 == validity_duration.rel_value_us)
     155              :   {
     156            3 :     bool found = false;
     157              : 
     158            3 :     GNUNET_break (NULL == bs_pub);
     159            3 :     GNUNET_break (NULL == section_name);
     160           16 :     for (unsigned int i = 0; i<MAX_KEYS; i++)
     161           16 :       if (0 == GNUNET_memcmp (h_cs,
     162              :                               &keys[i].h_cs))
     163              :       {
     164            3 :         keys[i].valid = false;
     165            3 :         keys[i].revoked = false;
     166            3 :         TALER_denom_pub_free (&keys[i].denom_pub);
     167            3 :         GNUNET_assert (num_keys > 0);
     168            3 :         num_keys--;
     169            3 :         found = true;
     170            3 :         break;
     171              :       }
     172            3 :     if (! found)
     173            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     174              :                   "Error: helper announced expiration of unknown key!\n");
     175              : 
     176            3 :     return;
     177              :   }
     178              : 
     179           81 :   GNUNET_break (NULL != bs_pub);
     180          397 :   for (unsigned int i = 0; i<MAX_KEYS; i++)
     181          397 :     if (! keys[i].valid)
     182              :     {
     183           81 :       keys[i].valid = true;
     184           81 :       keys[i].h_cs = *h_cs;
     185           81 :       keys[i].start_time = start_time;
     186           81 :       keys[i].validity_duration = validity_duration;
     187              :       keys[i].denom_pub.bsign_pub_key
     188           81 :         = GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
     189           81 :       num_keys++;
     190           81 :       return;
     191              :     }
     192              :   /* too many keys! */
     193            0 :   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     194              :               "Error: received %d live keys from the service!\n",
     195              :               MAX_KEYS + 1);
     196              : }
     197              : 
     198              : 
     199              : /**
     200              :  * Test key revocation logic.
     201              :  *
     202              :  * @param dh handle to the helper
     203              :  * @return 0 on success
     204              :  */
     205              : static int
     206            1 : test_revocation (struct TALER_CRYPTO_CsDenominationHelper *dh)
     207              : {
     208            1 :   struct timespec req = {
     209              :     .tv_nsec = 250000000
     210              :   };
     211              : 
     212            4 :   for (unsigned int i = 0; i<NUM_REVOKES; i++)
     213              :   {
     214              :     uint32_t off;
     215              : 
     216            3 :     off = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
     217              :                                     num_keys);
     218              :     /* find index of key to revoke */
     219           16 :     for (unsigned int j = 0; j < MAX_KEYS; j++)
     220              :     {
     221           16 :       if (! keys[j].valid)
     222            0 :         continue;
     223           16 :       if (0 != off)
     224              :       {
     225           13 :         off--;
     226           13 :         continue;
     227              :       }
     228            3 :       keys[j].revoked = true;
     229            3 :       fprintf (stderr,
     230              :                "Revoking key %s ...",
     231            3 :                GNUNET_h2s (&keys[j].h_cs.hash));
     232            3 :       TALER_CRYPTO_helper_cs_revoke (dh,
     233            3 :                                      &keys[j].h_cs);
     234            6 :       for (unsigned int k = 0; k<1000; k++)
     235              :       {
     236            6 :         TALER_CRYPTO_helper_cs_poll (dh);
     237            6 :         if (! keys[j].revoked)
     238            3 :           break;
     239            3 :         nanosleep (&req, NULL);
     240            3 :         fprintf (stderr, ".");
     241              :       }
     242            3 :       if (keys[j].revoked)
     243              :       {
     244            0 :         fprintf (stderr,
     245              :                  "\nFAILED: timeout trying to revoke key %u\n",
     246              :                  j);
     247            0 :         TALER_CRYPTO_helper_cs_disconnect (dh);
     248            0 :         return 2;
     249              :       }
     250            3 :       fprintf (stderr, "\n");
     251            3 :       break;
     252              :     }
     253              :   }
     254            1 :   return 0;
     255              : }
     256              : 
     257              : 
     258              : /**
     259              :  * Test R derivation logic.
     260              :  *
     261              :  * @param dh handle to the helper
     262              :  * @return 0 on success
     263              :  */
     264              : static int
     265            1 : test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh)
     266              : {
     267              :   enum TALER_ErrorCode ec;
     268            1 :   bool success = false;
     269              :   struct TALER_PlanchetMasterSecretP ps;
     270              :   struct TALER_CoinSpendPrivateKeyP coin_priv;
     271              :   union GNUNET_CRYPTO_BlindingSecretP bks;
     272              :   struct TALER_CoinPubHashP c_hash;
     273            1 :   struct GNUNET_CRYPTO_BlindingInputValues bi = {
     274              :     .cipher = GNUNET_CRYPTO_BSA_CS
     275              :   };
     276            1 :   struct TALER_ExchangeBlindingValues alg_values = {
     277              :     .blinding_inputs = &bi
     278              :   };
     279              :   union GNUNET_CRYPTO_BlindSessionNonce nonce;
     280              : 
     281            1 :   TALER_planchet_master_setup_random (&ps);
     282         1025 :   for (unsigned int i = 0; i<MAX_KEYS; i++)
     283              :   {
     284              :     struct TALER_PlanchetDetail pd;
     285              : 
     286         1024 :     if (! keys[i].valid)
     287         1018 :       continue;
     288            6 :     GNUNET_assert (GNUNET_CRYPTO_BSA_CS ==
     289              :                    keys[i].denom_pub.bsign_pub_key->cipher);
     290              : #pragma message "phase out TALER_cs_withdraw_nonce_derive"
     291            6 :     TALER_cs_withdraw_nonce_derive (
     292              :       &ps,
     293              :       &nonce.cs_nonce);
     294            6 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     295              :                 "Requesting R derivation with key %s\n",
     296              :                 GNUNET_h2s (&keys[i].h_cs.hash));
     297              :     {
     298            6 :       struct TALER_CRYPTO_CsDeriveRequest cdr = {
     299            6 :         .h_cs = &keys[i].h_cs,
     300              :         .nonce = &nonce.cs_nonce
     301              :       };
     302              : 
     303            6 :       ec = TALER_CRYPTO_helper_cs_r_derive (
     304              :         dh,
     305              :         &cdr,
     306              :         false,
     307              :         &bi.details.cs_values);
     308              :     }
     309            6 :     switch (ec)
     310              :     {
     311            1 :     case TALER_EC_NONE:
     312            1 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
     313              :                                       keys[i].start_time.abs_time),
     314              :                                     >,
     315              :                                     GNUNET_TIME_UNIT_SECONDS))
     316              :       {
     317              :         /* key worked too early */
     318            0 :         GNUNET_break (0);
     319            0 :         return 4;
     320              :       }
     321            1 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
     322              :                                       keys[i].start_time.abs_time),
     323              :                                     >,
     324              :                                     keys[i].validity_duration))
     325              :       {
     326              :         /* key worked too later */
     327            0 :         GNUNET_break (0);
     328            0 :         return 5;
     329              :       }
     330              : 
     331            1 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     332              :                   "Received valid R for key %s\n",
     333              :                   GNUNET_h2s (&keys[i].h_cs.hash));
     334            1 :       TALER_planchet_setup_coin_priv (&ps,
     335              :                                       &alg_values,
     336              :                                       &coin_priv);
     337            1 :       TALER_planchet_blinding_secret_create (&ps,
     338              :                                              &alg_values,
     339              :                                              &bks);
     340            1 :       GNUNET_assert (GNUNET_OK ==
     341              :                      TALER_planchet_prepare (&keys[i].denom_pub,
     342              :                                              &alg_values,
     343              :                                              &bks,
     344              :                                              &nonce,
     345              :                                              &coin_priv,
     346              :                                              NULL, /* no age commitment */
     347              :                                              &c_hash,
     348              :                                              &pd));
     349            1 :       TALER_blinded_planchet_free (&pd.blinded_planchet);
     350            1 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     351              :                   "Successfully prepared planchet");
     352            1 :       success = true;
     353            1 :       break;
     354            5 :     case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
     355              :       /* This 'failure' is expected, we're testing also for the
     356              :          error handling! */
     357            5 :       if ( (GNUNET_TIME_relative_is_zero (
     358              :               GNUNET_TIME_absolute_get_remaining (
     359            0 :                 keys[i].start_time.abs_time))) &&
     360            0 :            (GNUNET_TIME_relative_cmp (
     361              :               GNUNET_TIME_absolute_get_duration (
     362              :                 keys[i].start_time.abs_time),
     363              :               <,
     364              :               keys[i].validity_duration)) )
     365              :       {
     366              :         /* key should have worked! */
     367            0 :         GNUNET_break (0);
     368            0 :         return 6;
     369              :       }
     370            5 :       break;
     371            0 :     default:
     372              :       /* unexpected error */
     373            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     374              :                   "Unexpected error %d\n",
     375              :                   ec);
     376            0 :       return 7;
     377              :     }
     378              :   }
     379            1 :   if (! success)
     380              :   {
     381              :     /* no valid key for signing found, also bad */
     382            0 :     GNUNET_break (0);
     383            0 :     return 16;
     384              :   }
     385              : 
     386              :   /* check R derivation does not work if the key is unknown */
     387              :   {
     388              :     struct TALER_CsPubHashP rnd;
     389              :     struct GNUNET_CRYPTO_CSPublicRPairP crp;
     390            1 :     struct TALER_CRYPTO_CsDeriveRequest cdr = {
     391              :       .h_cs = &rnd,
     392              :       .nonce = &nonce.cs_nonce,
     393              :     };
     394              : 
     395            1 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     396              :                                 &rnd,
     397              :                                 sizeof (rnd));
     398            1 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     399              :                                 &nonce,
     400              :                                 sizeof (nonce));
     401            1 :     ec = TALER_CRYPTO_helper_cs_r_derive (dh,
     402              :                                           &cdr,
     403              :                                           false,
     404              :                                           &crp);
     405            1 :     if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
     406              :     {
     407            0 :       GNUNET_break (0);
     408            0 :       return 17;
     409              :     }
     410            1 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     411              :                 "R derivation with invalid key %s failed as desired\n",
     412              :                 GNUNET_h2s (&rnd.hash));
     413              :   }
     414            1 :   return 0;
     415              : }
     416              : 
     417              : 
     418              : /**
     419              :  * Test signing logic.
     420              :  *
     421              :  * @param dh handle to the helper
     422              :  * @return 0 on success
     423              :  */
     424              : static int
     425            1 : test_signing (struct TALER_CRYPTO_CsDenominationHelper *dh)
     426              : {
     427              :   struct TALER_BlindedDenominationSignature ds;
     428              :   enum TALER_ErrorCode ec;
     429            1 :   bool success = false;
     430              :   struct TALER_PlanchetMasterSecretP ps;
     431              :   struct TALER_CoinSpendPrivateKeyP coin_priv;
     432              :   union GNUNET_CRYPTO_BlindingSecretP bks;
     433              :   struct TALER_CoinPubHashP c_hash;
     434            1 :   struct GNUNET_CRYPTO_BlindingInputValues bi = {
     435              :     .cipher = GNUNET_CRYPTO_BSA_CS
     436              :   };
     437            1 :   struct TALER_ExchangeBlindingValues alg_values = {
     438              :     .blinding_inputs = &bi
     439              :   };
     440              :   union GNUNET_CRYPTO_BlindSessionNonce nonce;
     441              : 
     442            1 :   TALER_planchet_master_setup_random (&ps);
     443         1025 :   for (unsigned int i = 0; i<MAX_KEYS; i++)
     444              :   {
     445         1024 :     if (! keys[i].valid)
     446         1018 :       continue;
     447              :     {
     448              :       struct TALER_PlanchetDetail pd;
     449              :       struct TALER_CRYPTO_CsSignRequest csr;
     450            6 :       struct TALER_CRYPTO_CsDeriveRequest cdr = {
     451            6 :         .h_cs = &keys[i].h_cs,
     452              :         .nonce = &nonce.cs_nonce
     453              :       };
     454              : 
     455            6 :       TALER_cs_withdraw_nonce_derive (&ps,
     456              :                                       &nonce.cs_nonce);
     457            6 :       ec = TALER_CRYPTO_helper_cs_r_derive (
     458              :         dh,
     459              :         &cdr,
     460              :         false,
     461              :         &bi.details.cs_values);
     462            6 :       if (TALER_EC_NONE != ec)
     463            5 :         continue;
     464            1 :       TALER_planchet_setup_coin_priv (&ps,
     465              :                                       &alg_values,
     466              :                                       &coin_priv);
     467            1 :       TALER_planchet_blinding_secret_create (&ps,
     468              :                                              &alg_values,
     469              :                                              &bks);
     470            1 :       GNUNET_assert (GNUNET_YES ==
     471              :                      TALER_planchet_prepare (&keys[i].denom_pub,
     472              :                                              &alg_values,
     473              :                                              &bks,
     474              :                                              &nonce,
     475              :                                              &coin_priv,
     476              :                                              NULL, /* no age commitment */
     477              :                                              &c_hash,
     478              :                                              &pd));
     479            1 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     480              :                   "Requesting signature with key %s\n",
     481              :                   GNUNET_h2s (&keys[i].h_cs.hash));
     482            1 :       csr.h_cs = &keys[i].h_cs;
     483              :       csr.blinded_planchet
     484            1 :         = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
     485            1 :       ec = TALER_CRYPTO_helper_cs_sign (
     486              :         dh,
     487              :         &csr,
     488              :         false,
     489              :         &ds);
     490            1 :       TALER_blinded_planchet_free (&pd.blinded_planchet);
     491              :     }
     492            1 :     switch (ec)
     493              :     {
     494            1 :     case TALER_EC_NONE:
     495            1 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
     496              :                                       keys[i].start_time.abs_time),
     497              :                                     >,
     498              :                                     GNUNET_TIME_UNIT_SECONDS))
     499              :       {
     500              :         /* key worked too early */
     501            0 :         GNUNET_break (0);
     502            0 :         TALER_blinded_denom_sig_free (&ds);
     503            0 :         return 4;
     504              :       }
     505            1 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
     506              :                                       keys[i].start_time.abs_time),
     507              :                                     >,
     508              :                                     keys[i].validity_duration))
     509              :       {
     510              :         /* key worked too later */
     511            0 :         GNUNET_break (0);
     512            0 :         TALER_blinded_denom_sig_free (&ds);
     513            0 :         return 5;
     514              :       }
     515              :       {
     516              :         struct TALER_FreshCoin coin;
     517              : 
     518            1 :         if (GNUNET_OK !=
     519            1 :             TALER_planchet_to_coin (&keys[i].denom_pub,
     520              :                                     &ds,
     521              :                                     &bks,
     522              :                                     &coin_priv,
     523              :                                     NULL, /* no age commitment */
     524              :                                     &c_hash,
     525              :                                     &alg_values,
     526              :                                     &coin))
     527              :         {
     528            0 :           GNUNET_break (0);
     529            0 :           TALER_blinded_denom_sig_free (&ds);
     530            0 :           return 6;
     531              :         }
     532            1 :         TALER_blinded_denom_sig_free (&ds);
     533            1 :         TALER_denom_sig_free (&coin.sig);
     534              :       }
     535            1 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     536              :                   "Received valid signature for key %s\n",
     537              :                   GNUNET_h2s (&keys[i].h_cs.hash));
     538            1 :       success = true;
     539            1 :       break;
     540            0 :     case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
     541              :       /* This 'failure' is expected, we're testing also for the
     542              :          error handling! */
     543            0 :       if ( (GNUNET_TIME_relative_is_zero (
     544              :               GNUNET_TIME_absolute_get_remaining (
     545            0 :                 keys[i].start_time.abs_time))) &&
     546            0 :            (GNUNET_TIME_relative_cmp (
     547              :               GNUNET_TIME_absolute_get_duration (
     548              :                 keys[i].start_time.abs_time),
     549              :               <,
     550              :               keys[i].validity_duration)) )
     551              :       {
     552              :         /* key should have worked! */
     553            0 :         GNUNET_break (0);
     554            0 :         return 6;
     555              :       }
     556            0 :       break;
     557            0 :     default:
     558              :       /* unexpected error */
     559            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     560              :                   "Unexpected error %d\n",
     561              :                   ec);
     562            0 :       return 7;
     563              :     }
     564              :   }
     565            1 :   if (! success)
     566              :   {
     567              :     /* no valid key for signing found, also bad */
     568            0 :     GNUNET_break (0);
     569            0 :     return 16;
     570              :   }
     571              : 
     572              :   /* check signing does not work if the key is unknown */
     573              :   {
     574              :     struct TALER_PlanchetDetail pd;
     575              :     struct TALER_CsPubHashP rnd;
     576              :     struct TALER_CRYPTO_CsSignRequest csr;
     577              : 
     578            1 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     579              :                                 &rnd,
     580              :                                 sizeof (rnd));
     581            1 :     GNUNET_assert (GNUNET_YES ==
     582              :                    TALER_planchet_prepare (&keys[0].denom_pub,
     583              :                                            &alg_values,
     584              :                                            &bks,
     585              :                                            &nonce,
     586              :                                            &coin_priv,
     587              :                                            NULL, /* no age commitment */
     588              :                                            &c_hash,
     589              :                                            &pd));
     590            1 :     csr.h_cs = &rnd;
     591              :     csr.blinded_planchet
     592            1 :       = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
     593            1 :     ec = TALER_CRYPTO_helper_cs_sign (
     594              :       dh,
     595              :       &csr,
     596              :       false,
     597              :       &ds);
     598            1 :     TALER_blinded_planchet_free (&pd.blinded_planchet);
     599            1 :     if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
     600              :     {
     601            0 :       if (TALER_EC_NONE == ec)
     602            0 :         TALER_blinded_denom_sig_free (&ds);
     603            0 :       GNUNET_break (0);
     604            0 :       return 17;
     605              :     }
     606            1 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     607              :                 "Signing with invalid key %s failed as desired\n",
     608              :                 GNUNET_h2s (&rnd.hash));
     609              :   }
     610            1 :   return 0;
     611              : }
     612              : 
     613              : 
     614              : /**
     615              :  * Test batch signing logic.
     616              :  *
     617              :  * @param dh handle to the helper
     618              :  * @param batch_size how large should the batch be
     619              :  * @param check_sigs also check unknown key and signatures
     620              :  * @return 0 on success
     621              :  */
     622              : static int
     623            6 : test_batch_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
     624              :                     unsigned int batch_size,
     625              :                     bool check_sigs)
     626            6 : {
     627            6 :   struct TALER_BlindedDenominationSignature ds[batch_size];
     628              :   enum TALER_ErrorCode ec;
     629            6 :   bool success = false;
     630            6 :   struct TALER_PlanchetMasterSecretP ps[batch_size];
     631            6 :   struct TALER_CoinSpendPrivateKeyP coin_priv[batch_size];
     632            6 :   union GNUNET_CRYPTO_BlindingSecretP bks[batch_size];
     633            6 :   struct TALER_CoinPubHashP c_hash[batch_size];
     634            6 :   struct GNUNET_CRYPTO_BlindingInputValues bi[batch_size];
     635            6 :   struct TALER_ExchangeBlindingValues alg_values[batch_size];
     636            6 :   union GNUNET_CRYPTO_BlindSessionNonce nonces[batch_size];
     637              : 
     638          157 :   for (unsigned int i = 0; i<batch_size; i++)
     639          151 :     TALER_planchet_master_setup_random (&ps[i]);
     640         6150 :   for (unsigned int k = 0; k<MAX_KEYS; k++)
     641              :   {
     642         6144 :     if (! keys[k].valid)
     643         6108 :       continue;
     644           36 :     {
     645           36 :       struct TALER_PlanchetDetail pd[batch_size];
     646           36 :       struct TALER_CRYPTO_CsSignRequest csr[batch_size];
     647           36 :       struct TALER_CRYPTO_CsDeriveRequest cdr[batch_size];
     648           36 :       struct GNUNET_CRYPTO_CSPublicRPairP crps[batch_size];
     649              : 
     650          942 :       for (unsigned int i = 0; i<batch_size; i++)
     651              :       {
     652          906 :         cdr[i].h_cs = &keys[k].h_cs;
     653          906 :         cdr[i].nonce = &nonces[i].cs_nonce;
     654          906 :         TALER_cs_withdraw_nonce_derive (
     655          906 :           &ps[i],
     656              :           &nonces[i].cs_nonce);
     657          906 :         bi[i].cipher = GNUNET_CRYPTO_BSA_CS;
     658          906 :         alg_values[i].blinding_inputs = &bi[i];
     659              :       }
     660           36 :       ec = TALER_CRYPTO_helper_cs_r_batch_derive (
     661              :         dh,
     662              :         batch_size,
     663              :         cdr,
     664              :         false,
     665              :         crps);
     666           36 :       if (TALER_EC_NONE != ec)
     667           30 :         continue;
     668          157 :       for (unsigned int i = 0; i<batch_size; i++)
     669              :       {
     670          151 :         bi[i].details.cs_values = crps[i];
     671          151 :         TALER_planchet_setup_coin_priv (&ps[i],
     672          151 :                                         &alg_values[i],
     673              :                                         &coin_priv[i]);
     674          151 :         TALER_planchet_blinding_secret_create (&ps[i],
     675          151 :                                                &alg_values[i],
     676              :                                                &bks[i]);
     677          151 :         GNUNET_assert (GNUNET_YES ==
     678              :                        TALER_planchet_prepare (&keys[k].denom_pub,
     679              :                                                &alg_values[i],
     680              :                                                &bks[i],
     681              :                                                &nonces[i],
     682              :                                                &coin_priv[i],
     683              :                                                NULL, /* no age commitment */
     684              :                                                &c_hash[i],
     685              :                                                &pd[i]));
     686          151 :         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     687              :                     "Requesting signature with key %s\n",
     688              :                     GNUNET_h2s (&keys[k].h_cs.hash));
     689          151 :         csr[i].h_cs = &keys[k].h_cs;
     690              :         csr[i].blinded_planchet
     691          151 :           = &pd[i].blinded_planchet.blinded_message->details.cs_blinded_message;
     692              :       }
     693            6 :       ec = TALER_CRYPTO_helper_cs_batch_sign (
     694              :         dh,
     695              :         batch_size,
     696              :         csr,
     697              :         false,
     698              :         ds);
     699          157 :       for (unsigned int i = 0; i<batch_size; i++)
     700              :       {
     701          151 :         TALER_blinded_planchet_free (&pd[i].blinded_planchet);
     702              :       }
     703              :     }
     704            6 :     switch (ec)
     705              :     {
     706            6 :     case TALER_EC_NONE:
     707            6 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
     708              :                                       keys[k].start_time.abs_time),
     709              :                                     >,
     710              :                                     GNUNET_TIME_UNIT_SECONDS))
     711              :       {
     712              :         /* key worked too early */
     713            0 :         GNUNET_break (0);
     714            0 :         return 4;
     715              :       }
     716            6 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
     717              :                                       keys[k].start_time.abs_time),
     718              :                                     >,
     719              :                                     keys[k].validity_duration))
     720              :       {
     721              :         /* key worked too later */
     722            0 :         GNUNET_break (0);
     723            0 :         return 5;
     724              :       }
     725            6 :       if (check_sigs)
     726              :       {
     727           68 :         for (unsigned int i = 0; i<batch_size; i++)
     728              :         {
     729              :           struct TALER_FreshCoin coin;
     730              : 
     731           66 :           if (GNUNET_OK !=
     732           66 :               TALER_planchet_to_coin (&keys[k].denom_pub,
     733           66 :                                       &ds[i],
     734           66 :                                       &bks[i],
     735           66 :                                       &coin_priv[i],
     736              :                                       NULL, /* no age commitment */
     737           66 :                                       &c_hash[i],
     738           66 :                                       &alg_values[i],
     739              :                                       &coin))
     740              :           {
     741            0 :             GNUNET_break (0);
     742            0 :             return 6;
     743              :           }
     744           66 :           TALER_blinded_denom_sig_free (&ds[i]);
     745           66 :           TALER_denom_sig_free (&coin.sig);
     746              :         }
     747            2 :         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     748              :                     "Received valid signature for key %s\n",
     749              :                     GNUNET_h2s (&keys[k].h_cs.hash));
     750              :       }
     751              :       else
     752              :       {
     753           89 :         for (unsigned int i = 0; i<batch_size; i++)
     754           85 :           TALER_blinded_denom_sig_free (&ds[i]);
     755              :       }
     756            6 :       success = true;
     757            6 :       break;
     758            0 :     case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
     759              :       /* This 'failure' is expected, we're testing also for the
     760              :          error handling! */
     761            0 :       if ( (GNUNET_TIME_relative_is_zero (
     762              :               GNUNET_TIME_absolute_get_remaining (
     763            0 :                 keys[k].start_time.abs_time))) &&
     764            0 :            (GNUNET_TIME_relative_cmp (
     765              :               GNUNET_TIME_absolute_get_duration (
     766              :                 keys[k].start_time.abs_time),
     767              :               <,
     768              :               keys[k].validity_duration)) )
     769              :       {
     770              :         /* key should have worked! */
     771            0 :         GNUNET_break (0);
     772            0 :         return 6;
     773              :       }
     774            0 :       break;
     775            0 :     default:
     776              :       /* unexpected error */
     777            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     778              :                   "Unexpected error %d\n",
     779              :                   ec);
     780            0 :       return 7;
     781              :     }
     782              :   }
     783            6 :   if (! success)
     784              :   {
     785              :     /* no valid key for signing found, also bad */
     786            0 :     GNUNET_break (0);
     787            0 :     return 16;
     788              :   }
     789              : 
     790              :   /* check signing does not work if the key is unknown */
     791            6 :   if (check_sigs)
     792              :   {
     793              :     struct TALER_PlanchetDetail pd;
     794              :     struct TALER_CsPubHashP rnd;
     795              :     struct TALER_CRYPTO_CsSignRequest csr;
     796              : 
     797            2 :     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
     798              :                                 &rnd,
     799              :                                 sizeof (rnd));
     800            2 :     GNUNET_assert (GNUNET_YES ==
     801              :                    TALER_planchet_prepare (&keys[0].denom_pub,
     802              :                                            &alg_values[0],
     803              :                                            &bks[0],
     804              :                                            &nonces[0],
     805              :                                            &coin_priv[0],
     806              :                                            NULL, /* no age commitment */
     807              :                                            &c_hash[0],
     808              :                                            &pd));
     809            2 :     csr.h_cs = &rnd;
     810              :     csr.blinded_planchet
     811            2 :       = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
     812            2 :     ec = TALER_CRYPTO_helper_cs_batch_sign (
     813              :       dh,
     814              :       1,
     815              :       &csr,
     816              :       false,
     817              :       &ds[0]);
     818            2 :     TALER_blinded_planchet_free (&pd.blinded_planchet);
     819            2 :     if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
     820              :     {
     821            0 :       if (TALER_EC_NONE == ec)
     822            0 :         TALER_blinded_denom_sig_free (&ds[0]);
     823            0 :       GNUNET_break (0);
     824            0 :       return 17;
     825              :     }
     826            2 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     827              :                 "Signing with invalid key %s failed as desired\n",
     828              :                 GNUNET_h2s (&rnd.hash));
     829              :   }
     830            6 :   return 0;
     831              : }
     832              : 
     833              : 
     834              : /**
     835              :  * Benchmark signing logic.
     836              :  *
     837              :  * @param dh handle to the helper
     838              :  * @return 0 on success
     839              :  */
     840              : static int
     841            9 : perf_signing (struct TALER_CRYPTO_CsDenominationHelper *dh,
     842              :               const char *type)
     843              : {
     844              :   struct TALER_BlindedDenominationSignature ds;
     845              :   enum TALER_ErrorCode ec;
     846              :   struct GNUNET_TIME_Relative duration;
     847              :   struct TALER_PlanchetMasterSecretP ps;
     848              :   struct TALER_CoinSpendPrivateKeyP coin_priv;
     849              :   union GNUNET_CRYPTO_BlindingSecretP bks;
     850            9 :   struct GNUNET_CRYPTO_BlindingInputValues bv = {
     851              :     .cipher = GNUNET_CRYPTO_BSA_CS
     852              :   };
     853            9 :   struct TALER_ExchangeBlindingValues alg_values = {
     854              :     .blinding_inputs = &bv
     855              :   };
     856              : 
     857            9 :   TALER_planchet_master_setup_random (&ps);
     858            9 :   duration = GNUNET_TIME_UNIT_ZERO;
     859            9 :   TALER_CRYPTO_helper_cs_poll (dh);
     860           18 :   for (unsigned int j = 0; j<NUM_SIGN_PERFS;)
     861              :   {
     862         9225 :     for (unsigned int i = 0; i<MAX_KEYS; i++)
     863              :     {
     864         9216 :       if (! keys[i].valid)
     865         9138 :         continue;
     866           78 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
     867              :                                       keys[i].start_time.abs_time),
     868              :                                     >,
     869              :                                     GNUNET_TIME_UNIT_SECONDS))
     870           69 :         continue;
     871            9 :       if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
     872              :                                       keys[i].start_time.abs_time),
     873              :                                     >,
     874              :                                     keys[i].validity_duration))
     875            0 :         continue;
     876              :       {
     877              :         struct TALER_CoinPubHashP c_hash;
     878              :         struct TALER_PlanchetDetail pd;
     879              :         union GNUNET_CRYPTO_BlindSessionNonce nonce;
     880            9 :         struct TALER_CRYPTO_CsDeriveRequest cdr = {
     881            9 :           .h_cs = &keys[i].h_cs,
     882              :           .nonce = &nonce.cs_nonce
     883              :         };
     884              : 
     885            9 :         TALER_cs_withdraw_nonce_derive (
     886              :           &ps,
     887              :           &nonce.cs_nonce);
     888            9 :         ec = TALER_CRYPTO_helper_cs_r_derive (
     889              :           dh,
     890              :           &cdr,
     891              :           true,
     892              :           &bv.details.cs_values);
     893            9 :         if (TALER_EC_NONE != ec)
     894            0 :           continue;
     895            9 :         TALER_planchet_setup_coin_priv (&ps,
     896              :                                         &alg_values,
     897              :                                         &coin_priv);
     898            9 :         TALER_planchet_blinding_secret_create (&ps,
     899              :                                                &alg_values,
     900              :                                                &bks);
     901            9 :         GNUNET_assert (GNUNET_YES ==
     902              :                        TALER_planchet_prepare (&keys[i].denom_pub,
     903              :                                                &alg_values,
     904              :                                                &bks,
     905              :                                                &nonce,
     906              :                                                &coin_priv,
     907              :                                                NULL, /* no age commitment */
     908              :                                                &c_hash,
     909              :                                                &pd));
     910              :         /* use this key as long as it works */
     911              :         while (1)
     912          891 :         {
     913          900 :           struct GNUNET_TIME_Absolute start = GNUNET_TIME_absolute_get ();
     914              :           struct GNUNET_TIME_Relative delay;
     915              :           struct TALER_CRYPTO_CsSignRequest csr;
     916              : 
     917          900 :           csr.h_cs = &keys[i].h_cs;
     918              :           csr.blinded_planchet
     919          900 :             = &pd.blinded_planchet.blinded_message->details.cs_blinded_message;
     920          900 :           ec = TALER_CRYPTO_helper_cs_sign (
     921              :             dh,
     922              :             &csr,
     923              :             true,
     924              :             &ds);
     925          900 :           if (TALER_EC_NONE != ec)
     926            0 :             break;
     927          900 :           delay = GNUNET_TIME_absolute_get_duration (start);
     928          900 :           duration = GNUNET_TIME_relative_add (duration,
     929              :                                                delay);
     930          900 :           TALER_blinded_denom_sig_free (&ds);
     931          900 :           j++;
     932          900 :           if (NUM_SIGN_PERFS <= j)
     933            9 :             break;
     934              :         }
     935            9 :         TALER_blinded_planchet_free (&pd.blinded_planchet);
     936              :       }
     937              :     }   /* for i */
     938              :   }   /* for j */
     939            9 :   fprintf (stderr,
     940              :            "%u (%s) signature operations took %s\n",
     941              :            (unsigned int) NUM_SIGN_PERFS,
     942              :            type,
     943              :            GNUNET_STRINGS_relative_time_to_string (duration,
     944              :                                                    GNUNET_YES));
     945            9 :   return 0;
     946              : }
     947              : 
     948              : 
     949              : /**
     950              :  * Parallel signing logic.
     951              :  *
     952              :  * @param esh handle to the helper
     953              :  * @return 0 on success
     954              :  */
     955              : static int
     956            1 : par_signing (struct GNUNET_CONFIGURATION_Handle *cfg)
     957              : {
     958              :   struct GNUNET_TIME_Absolute start;
     959              :   struct GNUNET_TIME_Relative duration;
     960              :   pid_t pids[NUM_CORES];
     961              :   struct TALER_CRYPTO_CsDenominationHelper *dh;
     962              : 
     963            1 :   start = GNUNET_TIME_absolute_get ();
     964            9 :   for (unsigned int i = 0; i<NUM_CORES; i++)
     965              :   {
     966            8 :     pids[i] = fork ();
     967           16 :     num_keys = 0;
     968           16 :     GNUNET_assert (-1 != pids[i]);
     969           16 :     if (0 == pids[i])
     970              :     {
     971              :       int ret;
     972              : 
     973            8 :       dh = TALER_CRYPTO_helper_cs_connect (cfg,
     974              :                                            "taler-exchange",
     975              :                                            &key_cb,
     976              :                                            NULL);
     977            8 :       GNUNET_assert (NULL != dh);
     978            8 :       ret = perf_signing (dh,
     979              :                           "parallel");
     980            8 :       TALER_CRYPTO_helper_cs_disconnect (dh);
     981            8 :       free_keys ();
     982            8 :       exit (ret);
     983              :     }
     984              :   }
     985            9 :   for (unsigned int i = 0; i<NUM_CORES; i++)
     986              :   {
     987              :     int wstatus;
     988              : 
     989            8 :     GNUNET_assert (pids[i] ==
     990              :                    waitpid (pids[i],
     991              :                             &wstatus,
     992              :                             0));
     993              :   }
     994            1 :   duration = GNUNET_TIME_absolute_get_duration (start);
     995            1 :   fprintf (stderr,
     996              :            "%u (parallel) signature operations took %s (total real time)\n",
     997              :            (unsigned int) NUM_SIGN_PERFS * NUM_CORES,
     998              :            GNUNET_STRINGS_relative_time_to_string (duration,
     999              :                                                    GNUNET_YES));
    1000            1 :   return 0;
    1001              : }
    1002              : 
    1003              : 
    1004              : /**
    1005              :  * Main entry point into the test logic with the helper already running.
    1006              :  */
    1007              : static int
    1008            1 : run_test (void)
    1009              : {
    1010              :   struct GNUNET_CONFIGURATION_Handle *cfg;
    1011              :   struct TALER_CRYPTO_CsDenominationHelper *dh;
    1012            1 :   struct timespec req = {
    1013              :     .tv_nsec = 250000000
    1014              :   };
    1015              :   int ret;
    1016              : 
    1017            1 :   cfg = GNUNET_CONFIGURATION_create (TALER_EXCHANGE_project_data ());
    1018            1 :   if (GNUNET_OK !=
    1019            1 :       GNUNET_CONFIGURATION_load (cfg,
    1020              :                                  "test_helper_cs.conf"))
    1021              :   {
    1022            0 :     GNUNET_break (0);
    1023            0 :     return 77;
    1024              :   }
    1025              : 
    1026            1 :   fprintf (stderr, "Waiting for helper to start ... ");
    1027            1 :   for (unsigned int i = 0; i<100; i++)
    1028              :   {
    1029            1 :     nanosleep (&req,
    1030              :                NULL);
    1031            1 :     dh = TALER_CRYPTO_helper_cs_connect (cfg,
    1032              :                                          "taler-exchange",
    1033              :                                          &key_cb,
    1034              :                                          NULL);
    1035            1 :     if (NULL != dh)
    1036            1 :       break;
    1037            0 :     fprintf (stderr, ".");
    1038              :   }
    1039            1 :   if (NULL == dh)
    1040              :   {
    1041            0 :     fprintf (stderr,
    1042              :              "\nFAILED: timeout trying to connect to helper\n");
    1043            0 :     GNUNET_CONFIGURATION_destroy (cfg);
    1044            0 :     return 1;
    1045              :   }
    1046            1 :   if (0 == num_keys)
    1047              :   {
    1048            0 :     fprintf (stderr,
    1049              :              "\nFAILED: timeout trying to connect to helper\n");
    1050            0 :     TALER_CRYPTO_helper_cs_disconnect (dh);
    1051            0 :     GNUNET_CONFIGURATION_destroy (cfg);
    1052            0 :     return 1;
    1053              :   }
    1054            1 :   fprintf (stderr,
    1055              :            " Done (%u keys)\n",
    1056              :            num_keys);
    1057            1 :   ret = 0;
    1058            1 :   if (0 == ret)
    1059            1 :     ret = test_revocation (dh);
    1060            1 :   if (0 == ret)
    1061            1 :     ret = test_r_derive (dh);
    1062            1 :   if (0 == ret)
    1063            1 :     ret = test_signing (dh);
    1064            1 :   if (0 == ret)
    1065            1 :     ret = test_batch_signing (dh,
    1066              :                               2,
    1067              :                               true);
    1068            1 :   if (0 == ret)
    1069            1 :     ret = test_batch_signing (dh,
    1070              :                               64,
    1071              :                               true);
    1072            5 :   for (unsigned int i = 0; i<4; i++)
    1073              :   {
    1074              :     static unsigned int batches[] = { 1, 4, 16, 64 };
    1075            4 :     unsigned int batch_size = batches[i];
    1076              :     struct GNUNET_TIME_Absolute start;
    1077              :     struct GNUNET_TIME_Relative duration;
    1078              : 
    1079            4 :     start = GNUNET_TIME_absolute_get ();
    1080            4 :     if (0 != ret)
    1081            0 :       break;
    1082            4 :     ret = test_batch_signing (dh,
    1083              :                               batch_size,
    1084              :                               false);
    1085            4 :     duration = GNUNET_TIME_absolute_get_duration (start);
    1086            4 :     fprintf (stderr,
    1087              :              "%4u (batch) signature operations took %s (total real time)\n",
    1088              :              (unsigned int) batch_size,
    1089              :              GNUNET_STRINGS_relative_time_to_string (duration,
    1090              :                                                      GNUNET_YES));
    1091              :   }
    1092            1 :   if (0 == ret)
    1093            1 :     ret = perf_signing (dh,
    1094              :                         "sequential");
    1095            1 :   TALER_CRYPTO_helper_cs_disconnect (dh);
    1096            1 :   free_keys ();
    1097            1 :   if (0 == ret)
    1098            1 :     ret = par_signing (cfg);
    1099              :   /* clean up our state */
    1100            1 :   GNUNET_CONFIGURATION_destroy (cfg);
    1101            1 :   return ret;
    1102              : }
    1103              : 
    1104              : 
    1105              : int
    1106            1 : main (int argc,
    1107              :       const char *const argv[])
    1108              : {
    1109              :   struct GNUNET_OS_Process *helper;
    1110              :   char *libexec_dir;
    1111              :   char *binary_name;
    1112              :   int ret;
    1113              :   enum GNUNET_OS_ProcessStatusType type;
    1114              :   unsigned long code;
    1115            1 :   const char *loglev = "WARNING";
    1116              : 
    1117              :   (void) argc;
    1118              :   (void) argv;
    1119            1 :   unsetenv ("XDG_DATA_HOME");
    1120            1 :   unsetenv ("XDG_CONFIG_HOME");
    1121            1 :   GNUNET_log_setup ("test-helper-cs",
    1122              :                     loglev,
    1123              :                     NULL);
    1124            1 :   libexec_dir = GNUNET_OS_installation_get_path (TALER_EXCHANGE_project_data (),
    1125              :                                                  GNUNET_OS_IPK_BINDIR);
    1126            1 :   GNUNET_asprintf (&binary_name,
    1127              :                    "%s/%s",
    1128              :                    libexec_dir,
    1129              :                    "taler-exchange-secmod-cs");
    1130            1 :   GNUNET_free (libexec_dir);
    1131            1 :   helper = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_ERR,
    1132              :                                     NULL, NULL, NULL,
    1133              :                                     binary_name,
    1134              :                                     binary_name,
    1135              :                                     "-c",
    1136              :                                     "test_helper_cs.conf",
    1137              :                                     "-L",
    1138              :                                     loglev,
    1139              :                                     NULL);
    1140            1 :   if (NULL == helper)
    1141              :   {
    1142            0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
    1143              :                               "exec",
    1144              :                               binary_name);
    1145            0 :     GNUNET_free (binary_name);
    1146            0 :     return 77;
    1147              :   }
    1148            1 :   GNUNET_free (binary_name);
    1149            1 :   ret = run_test ();
    1150              : 
    1151            1 :   GNUNET_OS_process_kill (helper,
    1152              :                           SIGTERM);
    1153            1 :   if (GNUNET_OK !=
    1154            1 :       GNUNET_OS_process_wait_status (helper,
    1155              :                                      &type,
    1156              :                                      &code))
    1157              :   {
    1158            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1159              :                 "Helper process did not die voluntarily, killing hard\n");
    1160            0 :     GNUNET_OS_process_kill (helper,
    1161              :                             SIGKILL);
    1162            0 :     ret = 4;
    1163              :   }
    1164            1 :   else if ( (GNUNET_OS_PROCESS_EXITED != type) ||
    1165            1 :             (0 != code) )
    1166              :   {
    1167            0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1168              :                 "Helper died with unexpected status %d/%d\n",
    1169              :                 (int) type,
    1170              :                 (int) code);
    1171            0 :     ret = 5;
    1172              :   }
    1173            1 :   GNUNET_OS_process_destroy (helper);
    1174            1 :   return ret;
    1175              : }
    1176              : 
    1177              : 
    1178              : /* end of test_helper_cs.c */
        

Generated by: LCOV version 2.0-1