LCOV - code coverage report
Current view: top level - util - test_helper_cs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 327 417 78.4 %
Date: 2025-06-05 21:03:14 Functions: 10 10 100.0 %

          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 "platform.h"
      22             : #include "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          15 :     for (unsigned int i = 0; i<MAX_KEYS; i++)
     161          15 :       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         396 :   for (unsigned int i = 0; i<MAX_KEYS; i++)
     181         396 :     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          15 :     for (unsigned int j = 0; j < MAX_KEYS; j++)
     220             :     {
     221          15 :       if (! keys[j].valid)
     222           0 :         continue;
     223          15 :       if (0 != off)
     224             :       {
     225          12 :         off--;
     226          12 :         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 1.16