LCOV - code coverage report
Current view: top level - util - secmod_rsa.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 523 686 76.2 %
Date: 2025-08-30 09:28:00 Functions: 32 32 100.0 %

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2014-2024 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/secmod_rsa.c
      18             :  * @brief Standalone process to perform private key RSA operations
      19             :  * @author Christian Grothoff
      20             :  *
      21             :  * Key design points:
      22             :  * - EVERY thread of the exchange will have its own pair of connections to the
      23             :  *   crypto helpers.  This way, every thread will also have its own /keys state
      24             :  *   and avoid the need to synchronize on those.
      25             :  * - auditor signatures and master signatures are to be kept in the exchange DB,
      26             :  *   and merged with the public keys of the helper by the exchange HTTPD!
      27             :  * - the main loop of the helper is SINGLE-THREADED, but there are
      28             :  *   threads for crypto-workers which do the signing in parallel, one per client.
      29             :  * - thread-safety: signing happens in parallel, thus when REMOVING private keys,
      30             :  *   we must ensure that all signers are done before we fully free() the
      31             :  *   private key. This is done by reference counting (as work is always
      32             :  *   assigned and collected by the main thread).
      33             :  */
      34             : #include "taler/platform.h"
      35             : #include "taler/taler_util.h"
      36             : #include "secmod_rsa.h"
      37             : #include <gcrypt.h>
      38             : #include <pthread.h>
      39             : #include "taler/taler_error_codes.h"
      40             : #include "taler/taler_signatures.h"
      41             : #include "secmod_common.h"
      42             : #include <poll.h>
      43             : 
      44             : 
      45             : /**
      46             :  * Information we keep per denomination.
      47             :  */
      48             : struct Denomination;
      49             : 
      50             : 
      51             : /**
      52             :  * One particular denomination key.
      53             :  */
      54             : struct DenominationKey
      55             : {
      56             : 
      57             :   /**
      58             :    * Kept in a DLL of the respective denomination. Sorted by anchor time.
      59             :    */
      60             :   struct DenominationKey *next;
      61             : 
      62             :   /**
      63             :    * Kept in a DLL of the respective denomination. Sorted by anchor time.
      64             :    */
      65             :   struct DenominationKey *prev;
      66             : 
      67             :   /**
      68             :    * Denomination this key belongs to.
      69             :    */
      70             :   struct Denomination *denom;
      71             : 
      72             :   /**
      73             :    * Name of the file this key is stored under.
      74             :    */
      75             :   char *filename;
      76             : 
      77             :   /**
      78             :    * The private key of the denomination.
      79             :    */
      80             :   struct GNUNET_CRYPTO_RsaPrivateKey *denom_priv;
      81             : 
      82             :   /**
      83             :    * The public key of the denomination.
      84             :    */
      85             :   struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
      86             : 
      87             :   /**
      88             :    * Message to transmit to clients to introduce this public key.
      89             :    */
      90             :   struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
      91             : 
      92             :   /**
      93             :    * Hash of this denomination's public key.
      94             :    */
      95             :   struct TALER_RsaPubHashP h_rsa;
      96             : 
      97             :   /**
      98             :    * Time at which this key is supposed to become valid.
      99             :    */
     100             :   struct GNUNET_TIME_Timestamp anchor;
     101             : 
     102             :   /**
     103             :    * Generation when this key was created or revoked.
     104             :    */
     105             :   uint64_t key_gen;
     106             : 
     107             :   /**
     108             :    * Reference counter. Counts the number of threads that are
     109             :    * using this key at this time.
     110             :    */
     111             :   unsigned int rc;
     112             : 
     113             :   /**
     114             :    * Flag set to true if this key has been purged and the memory
     115             :    * must be freed as soon as @e rc hits zero.
     116             :    */
     117             :   bool purge;
     118             : 
     119             : };
     120             : 
     121             : 
     122             : struct Denomination
     123             : {
     124             : 
     125             :   /**
     126             :    * Kept in a DLL. Sorted by #denomination_action_time().
     127             :    */
     128             :   struct Denomination *next;
     129             : 
     130             :   /**
     131             :    * Kept in a DLL. Sorted by #denomination_action_time().
     132             :    */
     133             :   struct Denomination *prev;
     134             : 
     135             :   /**
     136             :    * Head of DLL of actual keys of this denomination.
     137             :    */
     138             :   struct DenominationKey *keys_head;
     139             : 
     140             :   /**
     141             :    * Tail of DLL of actual keys of this denomination.
     142             :    */
     143             :   struct DenominationKey *keys_tail;
     144             : 
     145             :   /**
     146             :    * How long can coins be withdrawn (generated)?  Should be small
     147             :    * enough to limit how many coins will be signed into existence with
     148             :    * the same key, but large enough to still provide a reasonable
     149             :    * anonymity set.
     150             :    */
     151             :   struct GNUNET_TIME_Relative duration_withdraw;
     152             : 
     153             :   /**
     154             :    * What is the configuration section of this denomination type?  Also used
     155             :    * for the directory name where the denomination keys are stored.
     156             :    */
     157             :   char *section;
     158             : 
     159             :   /**
     160             :    * Length of (new) RSA keys (in bits).
     161             :    */
     162             :   uint32_t rsa_keysize;
     163             : };
     164             : 
     165             : 
     166             : /**
     167             :  * A semaphore.
     168             :  */
     169             : struct Semaphore
     170             : {
     171             :   /**
     172             :    * Mutex for the semaphore.
     173             :    */
     174             :   pthread_mutex_t mutex;
     175             : 
     176             :   /**
     177             :    * Condition variable for the semaphore.
     178             :    */
     179             :   pthread_cond_t cv;
     180             : 
     181             :   /**
     182             :    * Counter of the semaphore.
     183             :    */
     184             :   unsigned int ctr;
     185             : };
     186             : 
     187             : 
     188             : /**
     189             :  * Job in a batch sign request.
     190             :  */
     191             : struct BatchJob;
     192             : 
     193             : /**
     194             :  * Handle for a thread that does work in batch signing.
     195             :  */
     196             : struct Worker
     197             : {
     198             :   /**
     199             :    * Kept in a DLL.
     200             :    */
     201             :   struct Worker *prev;
     202             : 
     203             :   /**
     204             :    * Kept in a DLL.
     205             :    */
     206             :   struct Worker *next;
     207             : 
     208             :   /**
     209             :    * Job this worker should do next.
     210             :    */
     211             :   struct BatchJob *job;
     212             : 
     213             :   /**
     214             :    * Semaphore to signal the worker that a job is available.
     215             :    */
     216             :   struct Semaphore sem;
     217             : 
     218             :   /**
     219             :    * Handle for this thread.
     220             :    */
     221             :   pthread_t pt;
     222             : 
     223             :   /**
     224             :    * Set to true if the worker should terminate.
     225             :    */
     226             :   bool do_shutdown;
     227             : };
     228             : 
     229             : 
     230             : /**
     231             :  * Job in a batch sign request.
     232             :  */
     233             : struct BatchJob
     234             : {
     235             :   /**
     236             :    * Request we are working on.
     237             :    */
     238             :   const struct TALER_CRYPTO_SignRequest *sr;
     239             : 
     240             :   /**
     241             :    * Thread doing the work.
     242             :    */
     243             :   struct Worker *worker;
     244             : 
     245             :   /**
     246             :    * Result with the signature.
     247             :    */
     248             :   struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
     249             : 
     250             :   /**
     251             :    * Semaphore to signal that the job is finished.
     252             :    */
     253             :   struct Semaphore sem;
     254             : 
     255             :   /**
     256             :    * Computation status.
     257             :    */
     258             :   enum TALER_ErrorCode ec;
     259             : 
     260             : };
     261             : 
     262             : 
     263             : /**
     264             :  * Head of DLL of workers ready for more work.
     265             :  */
     266             : static struct Worker *worker_head;
     267             : 
     268             : /**
     269             :  * Tail of DLL of workers ready for more work.
     270             :  */
     271             : static struct Worker *worker_tail;
     272             : 
     273             : /**
     274             :  * Lock for manipulating the worker DLL.
     275             :  */
     276             : static pthread_mutex_t worker_lock;
     277             : 
     278             : /**
     279             :  * Total number of workers that were started.
     280             :  */
     281             : static unsigned int workers;
     282             : 
     283             : /**
     284             :  * Semaphore used to grab a worker.
     285             :  */
     286             : static struct Semaphore worker_sem;
     287             : 
     288             : /**
     289             :  * Command-line options for various TALER_SECMOD_XXX_run() functions.
     290             :  */
     291             : static struct TALER_SECMOD_Options *globals;
     292             : 
     293             : /**
     294             :  * Where do we store the keys?
     295             :  */
     296             : static char *keydir;
     297             : 
     298             : /**
     299             :  * How much should coin creation (@e duration_withdraw) duration overlap
     300             :  * with the next denomination?  Basically, the starting time of two
     301             :  * denominations is always @e duration_withdraw - #overlap_duration apart.
     302             :  */
     303             : static struct GNUNET_TIME_Relative overlap_duration;
     304             : 
     305             : /**
     306             :  * How long into the future do we pre-generate keys?
     307             :  */
     308             : static struct GNUNET_TIME_Relative lookahead_sign;
     309             : 
     310             : /**
     311             :  * All of our denominations, in a DLL. Sorted?
     312             :  */
     313             : static struct Denomination *denom_head;
     314             : 
     315             : /**
     316             :  * All of our denominations, in a DLL. Sorted?
     317             :  */
     318             : static struct Denomination *denom_tail;
     319             : 
     320             : /**
     321             :  * Map of hashes of public (RSA) keys to `struct DenominationKey *`
     322             :  * with the respective private keys.
     323             :  */
     324             : static struct GNUNET_CONTAINER_MultiHashMap *keys;
     325             : 
     326             : /**
     327             :  * Task run to generate new keys.
     328             :  */
     329             : static struct GNUNET_SCHEDULER_Task *keygen_task;
     330             : 
     331             : /**
     332             :  * Lock for the keys queue.
     333             :  */
     334             : static pthread_mutex_t keys_lock;
     335             : 
     336             : /**
     337             :  * Current key generation.
     338             :  */
     339             : static uint64_t key_gen;
     340             : 
     341             : 
     342             : /**
     343             :  * Generate the announcement message for @a dk.
     344             :  *
     345             :  * @param[in,out] dk denomination key to generate the announcement for
     346             :  */
     347             : static void
     348        3568 : generate_response (struct DenominationKey *dk)
     349             : {
     350        3568 :   struct Denomination *denom = dk->denom;
     351        3568 :   size_t nlen = strlen (denom->section) + 1;
     352             :   struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
     353             :   size_t buf_len;
     354             :   void *buf;
     355             :   void *p;
     356             :   size_t tlen;
     357             : 
     358        3568 :   buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dk->denom_pub,
     359             :                                                  &buf);
     360        3568 :   GNUNET_assert (buf_len < UINT16_MAX);
     361        3568 :   GNUNET_assert (nlen < UINT16_MAX);
     362        3568 :   tlen = buf_len + nlen + sizeof (*an);
     363        3568 :   GNUNET_assert (tlen < UINT16_MAX);
     364        3568 :   an = GNUNET_malloc (tlen);
     365        3568 :   an->header.size = htons ((uint16_t) tlen);
     366        3568 :   an->header.type = htons (TALER_HELPER_RSA_MT_AVAIL);
     367        3568 :   an->pub_size = htons ((uint16_t) buf_len);
     368        3568 :   an->section_name_len = htons ((uint16_t) nlen);
     369        3568 :   an->anchor_time = GNUNET_TIME_timestamp_hton (dk->anchor);
     370        3568 :   an->duration_withdraw = GNUNET_TIME_relative_hton (denom->duration_withdraw);
     371        3568 :   TALER_exchange_secmod_rsa_sign (&dk->h_rsa,
     372        3568 :                                   denom->section,
     373             :                                   dk->anchor,
     374             :                                   denom->duration_withdraw,
     375             :                                   &TES_smpriv,
     376             :                                   &an->secm_sig);
     377        3568 :   an->secm_pub = TES_smpub;
     378        3568 :   p = (void *) &an[1];
     379        3568 :   GNUNET_memcpy (p,
     380             :                  buf,
     381             :                  buf_len);
     382        3568 :   GNUNET_free (buf);
     383        3568 :   GNUNET_memcpy (p + buf_len,
     384             :                  denom->section,
     385             :                  nlen);
     386        3568 :   dk->an = an;
     387        3568 : }
     388             : 
     389             : 
     390             : /**
     391             :  * Do the actual signing work.
     392             :  *
     393             :  * @param h_rsa key to sign with
     394             :  * @param bm blinded message to sign
     395             :  * @param[out] rsa_signaturep set to the RSA signature
     396             :  * @return #TALER_EC_NONE on success
     397             :  */
     398             : static enum TALER_ErrorCode
     399        1609 : do_sign (const struct TALER_RsaPubHashP *h_rsa,
     400             :          const struct GNUNET_CRYPTO_RsaBlindedMessage *bm,
     401             :          struct GNUNET_CRYPTO_RsaSignature **rsa_signaturep)
     402             : {
     403             :   struct DenominationKey *dk;
     404             :   struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
     405        1609 :   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
     406             : 
     407        1598 :   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
     408        1630 :   dk = GNUNET_CONTAINER_multihashmap_get (keys,
     409             :                                           &h_rsa->hash);
     410        1630 :   if (NULL == dk)
     411             :   {
     412           3 :     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
     413           3 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     414             :                 "Signing request failed, denomination key %s unknown\n",
     415             :                 GNUNET_h2s (&h_rsa->hash));
     416           3 :     return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
     417             :   }
     418        1627 :   if (GNUNET_TIME_absolute_is_future (dk->anchor.abs_time))
     419             :   {
     420             :     /* it is too early */
     421         335 :     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
     422         334 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     423             :                 "Signing request failed, denomination key %s is not yet valid (%llu)\n",
     424             :                 GNUNET_h2s (&h_rsa->hash),
     425             :                 (unsigned long long) dk->anchor.abs_time.abs_value_us);
     426         335 :     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY;
     427             :   }
     428             : 
     429        1292 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     430             :               "Received request to sign over %u bytes with key %s\n",
     431             :               (unsigned int) bm->blinded_msg_size,
     432             :               GNUNET_h2s (&h_rsa->hash));
     433        1292 :   GNUNET_assert (dk->rc < UINT_MAX);
     434        1292 :   dk->rc++;
     435        1292 :   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
     436             :   rsa_signature
     437        1292 :     = GNUNET_CRYPTO_rsa_sign_blinded (dk->denom_priv,
     438             :                                       bm);
     439        1292 :   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
     440        1292 :   GNUNET_assert (dk->rc > 0);
     441        1292 :   dk->rc--;
     442        1292 :   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
     443        1292 :   if (NULL == rsa_signature)
     444             :   {
     445           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     446             :                 "Signing request failed, worker failed to produce signature\n");
     447           0 :     return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
     448             :   }
     449             : 
     450        1292 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     451             :               "Sending RSA signature after %s\n",
     452             :               GNUNET_TIME_relative2s (
     453             :                 GNUNET_TIME_absolute_get_duration (now),
     454             :                 GNUNET_YES));
     455        1292 :   *rsa_signaturep = rsa_signature;
     456        1292 :   return TALER_EC_NONE;
     457             : }
     458             : 
     459             : 
     460             : /**
     461             :  * Generate error response that signing failed.
     462             :  *
     463             :  * @param client client to send response to
     464             :  * @param ec error code to include
     465             :  * @return #GNUNET_OK on success
     466             :  */
     467             : static enum GNUNET_GenericReturnValue
     468         338 : fail_sign (struct TES_Client *client,
     469             :            enum TALER_ErrorCode ec)
     470             : {
     471         338 :   struct TALER_CRYPTO_SignFailure sf = {
     472         338 :     .header.size = htons (sizeof (sf)),
     473         338 :     .header.type = htons (TALER_HELPER_RSA_MT_RES_SIGN_FAILURE),
     474         338 :     .ec = htonl (ec)
     475             :   };
     476             : 
     477         338 :   return TES_transmit (client->csock,
     478             :                        &sf.header);
     479             : }
     480             : 
     481             : 
     482             : /**
     483             :  * Generate signature response.
     484             :  *
     485             :  * @param client client to send response to
     486             :  * @param[in] rsa_signature signature to send, freed by this function
     487             :  * @return #GNUNET_OK on success
     488             :  */
     489             : static enum GNUNET_GenericReturnValue
     490        1292 : send_signature (struct TES_Client *client,
     491             :                 struct GNUNET_CRYPTO_RsaSignature *rsa_signature)
     492             : {
     493             :   struct TALER_CRYPTO_SignResponse *sr;
     494             :   void *buf;
     495             :   size_t buf_size;
     496             :   size_t tsize;
     497             :   enum GNUNET_GenericReturnValue ret;
     498             : 
     499        1292 :   buf_size = GNUNET_CRYPTO_rsa_signature_encode (rsa_signature,
     500             :                                                  &buf);
     501        1292 :   GNUNET_CRYPTO_rsa_signature_free (rsa_signature);
     502        1292 :   tsize = sizeof (*sr) + buf_size;
     503        1292 :   GNUNET_assert (tsize < UINT16_MAX);
     504        1292 :   sr = GNUNET_malloc (tsize);
     505        1292 :   sr->header.size = htons (tsize);
     506        1292 :   sr->header.type = htons (TALER_HELPER_RSA_MT_RES_SIGNATURE);
     507        1292 :   GNUNET_memcpy (&sr[1],
     508             :                  buf,
     509             :                  buf_size);
     510        1292 :   GNUNET_free (buf);
     511        1292 :   ret = TES_transmit (client->csock,
     512        1292 :                       &sr->header);
     513        1292 :   GNUNET_free (sr);
     514        1292 :   return ret;
     515             : }
     516             : 
     517             : 
     518             : /**
     519             :  * Handle @a client request @a sr to create signature. Create the
     520             :  * signature using the respective key and return the result to
     521             :  * the client.
     522             :  *
     523             :  * @param client the client making the request
     524             :  * @param sr the request details
     525             :  * @return #GNUNET_OK on success
     526             :  */
     527             : static enum GNUNET_GenericReturnValue
     528         906 : handle_sign_request (struct TES_Client *client,
     529             :                      const struct TALER_CRYPTO_SignRequest *sr)
     530             : {
     531         906 :   struct GNUNET_CRYPTO_RsaBlindedMessage bm = {
     532         906 :     .blinded_msg = (void *) &sr[1],
     533         906 :     .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr)
     534             :   };
     535             :   struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
     536             :   enum TALER_ErrorCode ec;
     537             : 
     538         906 :   ec = do_sign (&sr->h_rsa,
     539             :                 &bm,
     540             :                 &rsa_signature);
     541         907 :   if (TALER_EC_NONE != ec)
     542             :   {
     543           6 :     return fail_sign (client,
     544             :                       ec);
     545             :   }
     546         901 :   return send_signature (client,
     547             :                          rsa_signature);
     548             : }
     549             : 
     550             : 
     551             : /**
     552             :  * Initialize a semaphore @a sem with a value of @a val.
     553             :  *
     554             :  * @param[out] sem semaphore to initialize
     555             :  * @param val initial value of the semaphore
     556             :  */
     557             : static void
     558        1063 : sem_init (struct Semaphore *sem,
     559             :           unsigned int val)
     560             : {
     561        1063 :   GNUNET_assert (0 ==
     562             :                  pthread_mutex_init (&sem->mutex,
     563             :                                      NULL));
     564        1063 :   GNUNET_assert (0 ==
     565             :                  pthread_cond_init (&sem->cv,
     566             :                                     NULL));
     567        1063 :   sem->ctr = val;
     568        1063 : }
     569             : 
     570             : 
     571             : /**
     572             :  * Decrement semaphore, blocks until this is possible.
     573             :  *
     574             :  * @param[in,out] sem semaphore to decrement
     575             :  */
     576             : static void
     577        2793 : sem_down (struct Semaphore *sem)
     578             : {
     579        2793 :   GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
     580        4020 :   while (0 == sem->ctr)
     581             :   {
     582        1221 :     pthread_cond_wait (&sem->cv,
     583             :                        &sem->mutex);
     584             :   }
     585        2799 :   sem->ctr--;
     586        2799 :   GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
     587        2789 : }
     588             : 
     589             : 
     590             : /**
     591             :  * Increment semaphore, blocks until this is possible.
     592             :  *
     593             :  * @param[in,out] sem semaphore to decrement
     594             :  */
     595             : static void
     596        2788 : sem_up (struct Semaphore *sem)
     597             : {
     598        2788 :   GNUNET_assert (0 == pthread_mutex_lock (&sem->mutex));
     599        2803 :   sem->ctr++;
     600        2803 :   GNUNET_assert (0 == pthread_mutex_unlock (&sem->mutex));
     601        2791 :   pthread_cond_signal (&sem->cv);
     602        2789 : }
     603             : 
     604             : 
     605             : /**
     606             :  * Release resources used by @a sem.
     607             :  *
     608             :  * @param[in] sem semaphore to release (except the memory itself)
     609             :  */
     610             : static void
     611        1063 : sem_done (struct Semaphore *sem)
     612             : {
     613        1063 :   GNUNET_break (0 == pthread_cond_destroy (&sem->cv));
     614        1063 :   GNUNET_break (0 == pthread_mutex_destroy (&sem->mutex));
     615        1063 : }
     616             : 
     617             : 
     618             : /**
     619             :  * Main logic of a worker thread. Grabs work, does it,
     620             :  * grabs more work.
     621             :  *
     622             :  * @param cls a `struct Worker *`
     623             :  * @returns cls
     624             :  */
     625             : static void *
     626         320 : worker (void *cls)
     627             : {
     628         320 :   struct Worker *w = cls;
     629             : 
     630             :   while (true)
     631             :   {
     632        1037 :     GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
     633        1043 :     GNUNET_CONTAINER_DLL_insert (worker_head,
     634             :                                  worker_tail,
     635             :                                  w);
     636        1043 :     GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
     637        1043 :     sem_up (&worker_sem);
     638        1040 :     sem_down (&w->sem);
     639        1028 :     if (w->do_shutdown)
     640         320 :       break;
     641             :     {
     642         708 :       struct BatchJob *bj = w->job;
     643         708 :       const struct TALER_CRYPTO_SignRequest *sr = bj->sr;
     644         708 :       struct GNUNET_CRYPTO_RsaBlindedMessage bm = {
     645         708 :         .blinded_msg = (void *) &sr[1],
     646         708 :         .blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr)
     647             :       };
     648             : 
     649         708 :       bj->ec = do_sign (&sr->h_rsa,
     650             :                         &bm,
     651             :                         &bj->rsa_signature);
     652         723 :       sem_up (&bj->sem);
     653         717 :       w->job = NULL;
     654             :     }
     655             :   }
     656         320 :   return w;
     657             : }
     658             : 
     659             : 
     660             : /**
     661             :  * Start batch job @a bj to sign @a sr.
     662             :  *
     663             :  * @param sr signature request to answer
     664             :  * @param[out] bj job data structure
     665             :  */
     666             : static void
     667         723 : start_job (const struct TALER_CRYPTO_SignRequest *sr,
     668             :            struct BatchJob *bj)
     669             : {
     670         723 :   sem_init (&bj->sem,
     671             :             0);
     672         723 :   bj->sr = sr;
     673         723 :   sem_down (&worker_sem);
     674         723 :   GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
     675         723 :   bj->worker = worker_head;
     676         723 :   GNUNET_CONTAINER_DLL_remove (worker_head,
     677             :                                worker_tail,
     678             :                                bj->worker);
     679         723 :   GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
     680         723 :   bj->worker->job = bj;
     681         723 :   sem_up (&bj->worker->sem);
     682         723 : }
     683             : 
     684             : 
     685             : /**
     686             :  * Finish a job @a bj for a @a client.
     687             :  *
     688             :  * @param client who made the request
     689             :  * @param[in,out] bj job to finish
     690             :  */
     691             : static void
     692         723 : finish_job (struct TES_Client *client,
     693             :             struct BatchJob *bj)
     694             : {
     695         723 :   sem_down (&bj->sem);
     696         723 :   sem_done (&bj->sem);
     697         723 :   if (TALER_EC_NONE != bj->ec)
     698             :   {
     699         332 :     fail_sign (client,
     700             :                bj->ec);
     701         332 :     return;
     702             :   }
     703         391 :   GNUNET_assert (NULL != bj->rsa_signature);
     704         391 :   send_signature (client,
     705             :                   bj->rsa_signature);
     706         391 :   bj->rsa_signature = NULL; /* freed in send_signature */
     707             : }
     708             : 
     709             : 
     710             : /**
     711             :  * Handle @a client request @a sr to create a batch of signature. Creates the
     712             :  * signatures using the respective key and return the results to the client.
     713             :  *
     714             :  * @param client the client making the request
     715             :  * @param bsr the request details
     716             :  * @return #GNUNET_OK on success
     717             :  */
     718             : static enum GNUNET_GenericReturnValue
     719          82 : handle_batch_sign_request (struct TES_Client *client,
     720             :                            const struct TALER_CRYPTO_BatchSignRequest *bsr)
     721          82 : {
     722          82 :   uint32_t bs = ntohl (bsr->batch_size);
     723          82 :   uint16_t size = ntohs (bsr->header.size) - sizeof (*bsr);
     724          82 :   const void *off = (const void *) &bsr[1];
     725          82 :   unsigned int idx = 0;
     726          82 :   struct BatchJob jobs[bs];
     727          82 :   bool failure = false;
     728             : 
     729          82 :   if (bs > TALER_MAX_COINS)
     730             :   {
     731           0 :     GNUNET_break_op (0);
     732           0 :     return GNUNET_SYSERR;
     733             :   }
     734         805 :   while ( (bs > 0) &&
     735             :           (size > sizeof (struct TALER_CRYPTO_SignRequest)) )
     736             :   {
     737         723 :     const struct TALER_CRYPTO_SignRequest *sr = off;
     738         723 :     uint16_t s = ntohs (sr->header.size);
     739             : 
     740         723 :     if (s > size)
     741             :     {
     742           0 :       failure = true;
     743           0 :       bs = idx;
     744           0 :       break;
     745             :     }
     746         723 :     start_job (sr,
     747         723 :                &jobs[idx++]);
     748         723 :     off += s;
     749         723 :     size -= s;
     750             :   }
     751          82 :   GNUNET_break_op (0 == size);
     752          82 :   bs = GNUNET_MIN (bs,
     753             :                    idx);
     754         805 :   for (unsigned int i = 0; i<bs; i++)
     755         723 :     finish_job (client,
     756             :                 &jobs[i]);
     757          82 :   if (failure)
     758             :   {
     759           0 :     struct TALER_CRYPTO_SignFailure sf = {
     760           0 :       .header.size = htons (sizeof (sf)),
     761           0 :       .header.type = htons (TALER_HELPER_RSA_MT_RES_BATCH_FAILURE),
     762           0 :       .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
     763             :     };
     764             : 
     765           0 :     GNUNET_break (0);
     766           0 :     return TES_transmit (client->csock,
     767             :                          &sf.header);
     768             :   }
     769          82 :   return GNUNET_OK;
     770             : }
     771             : 
     772             : 
     773             : /**
     774             :  * Start worker thread for batch processing.
     775             :  *
     776             :  * @return #GNUNET_OK on success
     777             :  */
     778             : static enum GNUNET_GenericReturnValue
     779         320 : start_worker (void)
     780             : {
     781             :   struct Worker *w;
     782             : 
     783         320 :   w = GNUNET_new (struct Worker);
     784         320 :   sem_init (&w->sem,
     785             :             0);
     786         320 :   if (0 != pthread_create (&w->pt,
     787             :                            NULL,
     788             :                            &worker,
     789             :                            w))
     790             :   {
     791           0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
     792             :                          "pthread_create");
     793           0 :     GNUNET_free (w);
     794           0 :     return GNUNET_SYSERR;
     795             :   }
     796         320 :   workers++;
     797         320 :   return GNUNET_OK;
     798             : }
     799             : 
     800             : 
     801             : /**
     802             :  * Stop all worker threads.
     803             :  */
     804             : static void
     805          20 : stop_workers (void)
     806             : {
     807         340 :   while (workers > 0)
     808             :   {
     809             :     struct Worker *w;
     810             :     void *result;
     811             : 
     812         320 :     sem_down (&worker_sem);
     813         320 :     GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
     814         320 :     w = worker_head;
     815         320 :     GNUNET_CONTAINER_DLL_remove (worker_head,
     816             :                                  worker_tail,
     817             :                                  w);
     818         320 :     GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
     819         320 :     w->do_shutdown = true;
     820         320 :     sem_up (&w->sem);
     821         320 :     pthread_join (w->pt,
     822             :                   &result);
     823         320 :     GNUNET_assert (result == w);
     824         320 :     sem_done (&w->sem);
     825         320 :     GNUNET_free (w);
     826         320 :     workers--;
     827             :   }
     828          20 : }
     829             : 
     830             : 
     831             : /**
     832             :  * Initialize key material for denomination key @a dk (also on disk).
     833             :  *
     834             :  * @param[in,out] dk denomination key to compute key material for
     835             :  * @param position where in the DLL will the @a dk go
     836             :  * @return #GNUNET_OK on success
     837             :  */
     838             : static enum GNUNET_GenericReturnValue
     839        3144 : setup_key (struct DenominationKey *dk,
     840             :            struct DenominationKey *position)
     841             : {
     842        3144 :   struct Denomination *denom = dk->denom;
     843             :   struct GNUNET_CRYPTO_RsaPrivateKey *priv;
     844             :   struct GNUNET_CRYPTO_RsaPublicKey *pub;
     845             :   size_t buf_size;
     846             :   void *buf;
     847             : 
     848        3144 :   priv = GNUNET_CRYPTO_rsa_private_key_create (denom->rsa_keysize);
     849        3144 :   if (NULL == priv)
     850             :   {
     851           0 :     GNUNET_break (0);
     852           0 :     GNUNET_SCHEDULER_shutdown ();
     853           0 :     globals->global_ret = EXIT_FAILURE;
     854           0 :     return GNUNET_SYSERR;
     855             :   }
     856        3144 :   pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
     857        3144 :   if (NULL == pub)
     858             :   {
     859           0 :     GNUNET_break (0);
     860           0 :     GNUNET_CRYPTO_rsa_private_key_free (priv);
     861           0 :     return GNUNET_SYSERR;
     862             :   }
     863        3144 :   buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
     864             :                                                    &buf);
     865        3144 :   GNUNET_CRYPTO_rsa_public_key_hash (pub,
     866             :                                      &dk->h_rsa.hash);
     867        3144 :   GNUNET_asprintf (&dk->filename,
     868             :                    "%s/%s/%llu",
     869             :                    keydir,
     870             :                    denom->section,
     871        3144 :                    (unsigned long long) (dk->anchor.abs_time.abs_value_us
     872        3144 :                                          / GNUNET_TIME_UNIT_SECONDS.rel_value_us
     873             :                                          ));
     874        3144 :   if (GNUNET_OK !=
     875        3144 :       GNUNET_DISK_fn_write (dk->filename,
     876             :                             buf,
     877             :                             buf_size,
     878             :                             GNUNET_DISK_PERM_USER_READ))
     879             :   {
     880           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
     881             :                               "write",
     882             :                               dk->filename);
     883           0 :     GNUNET_free (buf);
     884           0 :     GNUNET_CRYPTO_rsa_private_key_free (priv);
     885           0 :     GNUNET_CRYPTO_rsa_public_key_free (pub);
     886           0 :     return GNUNET_SYSERR;
     887             :   }
     888        3144 :   GNUNET_free (buf);
     889        3144 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     890             :               "Setup fresh private key %s at %s in `%s' (generation #%llu)\n",
     891             :               GNUNET_h2s (&dk->h_rsa.hash),
     892             :               GNUNET_TIME_timestamp2s (dk->anchor),
     893             :               dk->filename,
     894             :               (unsigned long long) key_gen);
     895        3144 :   dk->denom_priv = priv;
     896        3144 :   dk->denom_pub = pub;
     897        3144 :   dk->key_gen = key_gen;
     898        3144 :   generate_response (dk);
     899        3144 :   if (GNUNET_OK !=
     900        3144 :       GNUNET_CONTAINER_multihashmap_put (
     901             :         keys,
     902        3144 :         &dk->h_rsa.hash,
     903             :         dk,
     904             :         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
     905             :   {
     906           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     907             :                 "Duplicate private key created! Terminating.\n");
     908           0 :     GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
     909           0 :     GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
     910           0 :     GNUNET_free (dk->filename);
     911           0 :     GNUNET_free (dk->an);
     912           0 :     GNUNET_free (dk);
     913           0 :     return GNUNET_SYSERR;
     914             :   }
     915        3144 :   GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
     916             :                                      denom->keys_tail,
     917             :                                      position,
     918             :                                      dk);
     919        3144 :   return GNUNET_OK;
     920             : }
     921             : 
     922             : 
     923             : /**
     924             :  * The withdraw period of a key @a dk has expired. Purge it.
     925             :  *
     926             :  * @param[in] dk expired denomination key to purge
     927             :  */
     928             : static void
     929           3 : purge_key (struct DenominationKey *dk)
     930             : {
     931           3 :   if (dk->purge)
     932           0 :     return;
     933           3 :   if (0 != unlink (dk->filename))
     934           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
     935             :                               "unlink",
     936             :                               dk->filename);
     937           3 :   GNUNET_free (dk->filename);
     938           3 :   dk->purge = true;
     939           3 :   dk->key_gen = key_gen;
     940             : }
     941             : 
     942             : 
     943             : /**
     944             :  * A @a client informs us that a key has been revoked.
     945             :  * Check if the key is still in use, and if so replace (!)
     946             :  * it with a fresh key.
     947             :  *
     948             :  * @param client the client making the request
     949             :  * @param rr the revocation request
     950             :  */
     951             : static enum GNUNET_GenericReturnValue
     952           3 : handle_revoke_request (struct TES_Client *client,
     953             :                        const struct TALER_CRYPTO_RevokeRequest *rr)
     954             : {
     955             :   struct DenominationKey *dk;
     956             :   struct DenominationKey *ndk;
     957             :   struct Denomination *denom;
     958             : 
     959             :   (void) client;
     960           3 :   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
     961           3 :   dk = GNUNET_CONTAINER_multihashmap_get (keys,
     962             :                                           &rr->h_rsa.hash);
     963           3 :   if (NULL == dk)
     964             :   {
     965           0 :     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
     966           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     967             :                 "Revocation request ignored, denomination key %s unknown\n",
     968             :                 GNUNET_h2s (&rr->h_rsa.hash));
     969           0 :     return GNUNET_OK;
     970             :   }
     971           3 :   if (dk->purge)
     972             :   {
     973           0 :     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
     974           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     975             :                 "Revocation request ignored, denomination key %s already revoked\n",
     976             :                 GNUNET_h2s (&rr->h_rsa.hash));
     977           0 :     return GNUNET_OK;
     978             :   }
     979             : 
     980           3 :   key_gen++;
     981           3 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     982             :               "Revoking key %s, bumping generation to %llu\n",
     983             :               GNUNET_h2s (&rr->h_rsa.hash),
     984             :               (unsigned long long) key_gen);
     985           3 :   purge_key (dk);
     986             : 
     987             :   /* Setup replacement key */
     988           3 :   denom = dk->denom;
     989           3 :   ndk = GNUNET_new (struct DenominationKey);
     990           3 :   ndk->denom = denom;
     991           3 :   ndk->anchor = dk->anchor;
     992           3 :   if (GNUNET_OK !=
     993           3 :       setup_key (ndk,
     994             :                  dk))
     995             :   {
     996           0 :     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
     997           0 :     GNUNET_break (0);
     998           0 :     GNUNET_SCHEDULER_shutdown ();
     999           0 :     globals->global_ret = EXIT_FAILURE;
    1000           0 :     return GNUNET_SYSERR;
    1001             :   }
    1002           3 :   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
    1003           3 :   TES_wake_clients ();
    1004           3 :   return GNUNET_OK;
    1005             : }
    1006             : 
    1007             : 
    1008             : /**
    1009             :  * Handle @a hdr message received from @a client.
    1010             :  *
    1011             :  * @param client the client that received the message
    1012             :  * @param hdr message that was received
    1013             :  * @return #GNUNET_OK on success
    1014             :  */
    1015             : static enum GNUNET_GenericReturnValue
    1016         991 : rsa_work_dispatch (struct TES_Client *client,
    1017             :                    const struct GNUNET_MessageHeader *hdr)
    1018             : {
    1019         991 :   uint16_t msize = ntohs (hdr->size);
    1020             : 
    1021         991 :   switch (ntohs (hdr->type))
    1022             :   {
    1023         906 :   case TALER_HELPER_RSA_MT_REQ_SIGN:
    1024         906 :     if (msize <= sizeof (struct TALER_CRYPTO_SignRequest))
    1025             :     {
    1026           0 :       GNUNET_break_op (0);
    1027           0 :       return GNUNET_SYSERR;
    1028             :     }
    1029         906 :     return handle_sign_request (
    1030             :       client,
    1031             :       (const struct TALER_CRYPTO_SignRequest *) hdr);
    1032           3 :   case TALER_HELPER_RSA_MT_REQ_REVOKE:
    1033           3 :     if (msize != sizeof (struct TALER_CRYPTO_RevokeRequest))
    1034             :     {
    1035           0 :       GNUNET_break_op (0);
    1036           0 :       return GNUNET_SYSERR;
    1037             :     }
    1038           3 :     return handle_revoke_request (
    1039             :       client,
    1040             :       (const struct TALER_CRYPTO_RevokeRequest *) hdr);
    1041          82 :   case TALER_HELPER_RSA_MT_REQ_BATCH_SIGN:
    1042          82 :     if (msize <= sizeof (struct TALER_CRYPTO_BatchSignRequest))
    1043             :     {
    1044           0 :       GNUNET_break_op (0);
    1045           0 :       return GNUNET_SYSERR;
    1046             :     }
    1047          82 :     return handle_batch_sign_request (
    1048             :       client,
    1049             :       (const struct TALER_CRYPTO_BatchSignRequest *) hdr);
    1050           0 :   default:
    1051           0 :     GNUNET_break_op (0);
    1052           0 :     return GNUNET_SYSERR;
    1053             :   }
    1054             : }
    1055             : 
    1056             : 
    1057             : /**
    1058             :  * Send our initial key set to @a client together with the
    1059             :  * "sync" terminator.
    1060             :  *
    1061             :  * @param client the client to inform
    1062             :  * @return #GNUNET_OK on success
    1063             :  */
    1064             : static enum GNUNET_GenericReturnValue
    1065          38 : rsa_client_init (struct TES_Client *client)
    1066             : {
    1067          38 :   size_t obs = 0;
    1068             :   char *buf;
    1069             : 
    1070          38 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    1071             :               "Initializing new client %p\n",
    1072             :               client);
    1073          38 :   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
    1074          38 :   for (struct Denomination *denom = denom_head;
    1075         207 :        NULL != denom;
    1076         169 :        denom = denom->next)
    1077             :   {
    1078         169 :     for (struct DenominationKey *dk = denom->keys_head;
    1079        8045 :          NULL != dk;
    1080        7876 :          dk = dk->next)
    1081             :     {
    1082        7876 :       GNUNET_assert (obs + ntohs (dk->an->header.size)
    1083             :                      > obs);
    1084        7876 :       obs += ntohs (dk->an->header.size);
    1085             :     }
    1086             :   }
    1087          38 :   buf = GNUNET_malloc (obs);
    1088          38 :   obs = 0;
    1089          38 :   for (struct Denomination *denom = denom_head;
    1090         207 :        NULL != denom;
    1091         169 :        denom = denom->next)
    1092             :   {
    1093         169 :     for (struct DenominationKey *dk = denom->keys_head;
    1094        8045 :          NULL != dk;
    1095        7876 :          dk = dk->next)
    1096             :     {
    1097        7876 :       GNUNET_memcpy (&buf[obs],
    1098             :                      dk->an,
    1099             :                      ntohs (dk->an->header.size));
    1100        7876 :       GNUNET_assert (obs + ntohs (dk->an->header.size)
    1101             :                      > obs);
    1102        7876 :       obs += ntohs (dk->an->header.size);
    1103             :     }
    1104             :   }
    1105          38 :   client->key_gen = key_gen;
    1106          38 :   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
    1107          38 :   if (GNUNET_OK !=
    1108          38 :       TES_transmit_raw (client->csock,
    1109             :                         obs,
    1110             :                         buf))
    1111             :   {
    1112           0 :     GNUNET_free (buf);
    1113           0 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    1114             :                 "Client %p must have disconnected\n",
    1115             :                 client);
    1116           0 :     return GNUNET_SYSERR;
    1117             :   }
    1118          38 :   GNUNET_free (buf);
    1119             :   {
    1120          38 :     struct GNUNET_MessageHeader synced = {
    1121          38 :       .type = htons (TALER_HELPER_RSA_SYNCED),
    1122          38 :       .size = htons (sizeof (synced))
    1123             :     };
    1124             : 
    1125          38 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    1126             :                 "Sending RSA SYNCED message to %p\n",
    1127             :                 client);
    1128          38 :     if (GNUNET_OK !=
    1129          38 :         TES_transmit (client->csock,
    1130             :                       &synced))
    1131             :     {
    1132           0 :       GNUNET_break (0);
    1133           0 :       return GNUNET_SYSERR;
    1134             :     }
    1135             :   }
    1136          38 :   return GNUNET_OK;
    1137             : }
    1138             : 
    1139             : 
    1140             : /**
    1141             :  * Notify @a client about all changes to the keys since
    1142             :  * the last generation known to the @a client.
    1143             :  *
    1144             :  * @param client the client to notify
    1145             :  * @return #GNUNET_OK on success
    1146             :  */
    1147             : static enum GNUNET_GenericReturnValue
    1148          23 : rsa_update_client_keys (struct TES_Client *client)
    1149             : {
    1150          23 :   size_t obs = 0;
    1151             :   char *buf;
    1152             :   enum GNUNET_GenericReturnValue ret;
    1153             : 
    1154          23 :   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
    1155          23 :   for (struct Denomination *denom = denom_head;
    1156         107 :        NULL != denom;
    1157          84 :        denom = denom->next)
    1158             :   {
    1159          84 :     for (struct DenominationKey *key = denom->keys_head;
    1160        3673 :          NULL != key;
    1161        3589 :          key = key->next)
    1162             :     {
    1163        3589 :       if (key->key_gen <= client->key_gen)
    1164        3582 :         continue;
    1165           7 :       if (key->purge)
    1166           3 :         obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification);
    1167             :       else
    1168           4 :         obs += ntohs (key->an->header.size);
    1169             :     }
    1170             :   }
    1171          23 :   if (0 == obs)
    1172             :   {
    1173             :     /* nothing to do */
    1174          19 :     client->key_gen = key_gen;
    1175          19 :     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
    1176          19 :     return GNUNET_OK;
    1177             :   }
    1178           4 :   buf = GNUNET_malloc (obs);
    1179           4 :   obs = 0;
    1180           4 :   for (struct Denomination *denom = denom_head;
    1181           8 :        NULL != denom;
    1182           4 :        denom = denom->next)
    1183             :   {
    1184           4 :     for (struct DenominationKey *key = denom->keys_head;
    1185          35 :          NULL != key;
    1186          31 :          key = key->next)
    1187             :     {
    1188          31 :       if (key->key_gen <= client->key_gen)
    1189          24 :         continue;
    1190           7 :       if (key->purge)
    1191             :       {
    1192           3 :         struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
    1193           3 :           .header.type = htons (TALER_HELPER_RSA_MT_PURGE),
    1194           3 :           .header.size = htons (sizeof (pn)),
    1195             :           .h_rsa = key->h_rsa
    1196             :         };
    1197             : 
    1198           3 :         GNUNET_memcpy (&buf[obs],
    1199             :                        &pn,
    1200             :                        sizeof (pn));
    1201           3 :         GNUNET_assert (obs + sizeof (pn)
    1202             :                        > obs);
    1203           3 :         obs += sizeof (pn);
    1204             :       }
    1205             :       else
    1206             :       {
    1207           4 :         GNUNET_memcpy (&buf[obs],
    1208             :                        key->an,
    1209             :                        ntohs (key->an->header.size));
    1210           4 :         GNUNET_assert (obs + ntohs (key->an->header.size)
    1211             :                        > obs);
    1212           4 :         obs += ntohs (key->an->header.size);
    1213             :       }
    1214             :     }
    1215             :   }
    1216           4 :   client->key_gen = key_gen;
    1217           4 :   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
    1218           4 :   ret = TES_transmit_raw (client->csock,
    1219             :                           obs,
    1220             :                           buf);
    1221           4 :   GNUNET_free (buf);
    1222           4 :   return ret;
    1223             : }
    1224             : 
    1225             : 
    1226             : /**
    1227             :  * Create a new denomination key (we do not have enough).
    1228             :  *
    1229             :  * @param[in] denom denomination key to create
    1230             :  * @param now current time to use (to get many keys to use the exact same time)
    1231             :  * @return #GNUNET_OK on success
    1232             :  */
    1233             : static enum GNUNET_GenericReturnValue
    1234        3141 : create_key (struct Denomination *denom,
    1235             :             struct GNUNET_TIME_Timestamp now)
    1236             : {
    1237             :   struct DenominationKey *dk;
    1238             :   struct GNUNET_TIME_Timestamp anchor;
    1239             : 
    1240        3141 :   anchor = now;
    1241        3141 :   if (NULL != denom->keys_tail)
    1242             :   {
    1243             :     struct GNUNET_TIME_Absolute abs;
    1244             : 
    1245        3068 :     abs = GNUNET_TIME_absolute_add (denom->keys_tail->anchor.abs_time,
    1246             :                                     GNUNET_TIME_relative_subtract (
    1247             :                                       denom->duration_withdraw,
    1248             :                                       overlap_duration));
    1249        3068 :     if (GNUNET_TIME_absolute_cmp (now.abs_time,
    1250             :                                   <,
    1251             :                                   abs))
    1252        3068 :       anchor = GNUNET_TIME_absolute_to_timestamp (abs);
    1253             :   }
    1254        3141 :   dk = GNUNET_new (struct DenominationKey);
    1255        3141 :   dk->denom = denom;
    1256        3141 :   dk->anchor = anchor;
    1257        3141 :   if (GNUNET_OK !=
    1258        3141 :       setup_key (dk,
    1259             :                  denom->keys_tail))
    1260             :   {
    1261           0 :     GNUNET_break (0);
    1262           0 :     GNUNET_free (dk);
    1263           0 :     GNUNET_SCHEDULER_shutdown ();
    1264           0 :     globals->global_ret = EXIT_FAILURE;
    1265           0 :     return GNUNET_SYSERR;
    1266             :   }
    1267        3141 :   return GNUNET_OK;
    1268             : }
    1269             : 
    1270             : 
    1271             : /**
    1272             :  * At what time does this denomination require its next action?
    1273             :  * Basically, the minimum of the withdraw expiration time of the
    1274             :  * oldest denomination key, and the withdraw expiration time of
    1275             :  * the newest denomination key minus the #lookahead_sign time.
    1276             :  *
    1277             :  * @param denom denomination to compute action time for
    1278             :  */
    1279             : static struct GNUNET_TIME_Absolute
    1280         187 : denomination_action_time (const struct Denomination *denom)
    1281             : {
    1282         187 :   struct DenominationKey *head = denom->keys_head;
    1283         187 :   struct DenominationKey *tail = denom->keys_tail;
    1284             :   struct GNUNET_TIME_Absolute tt;
    1285             : 
    1286         187 :   if (NULL == head)
    1287           0 :     return GNUNET_TIME_UNIT_ZERO_ABS;
    1288         187 :   tt = GNUNET_TIME_absolute_subtract (
    1289             :     GNUNET_TIME_absolute_subtract (
    1290             :       GNUNET_TIME_absolute_add (tail->anchor.abs_time,
    1291             :                                 denom->duration_withdraw),
    1292             :       lookahead_sign),
    1293             :     overlap_duration);
    1294         187 :   if (head->rc > 0)
    1295           0 :     return tt; /* head expiration does not count due to rc > 0 */
    1296         187 :   return GNUNET_TIME_absolute_min (
    1297             :     GNUNET_TIME_absolute_add (head->anchor.abs_time,
    1298             :                               denom->duration_withdraw),
    1299             :     tt);
    1300             : }
    1301             : 
    1302             : 
    1303             : /**
    1304             :  * Create new keys and expire ancient keys of the given denomination @a denom.
    1305             :  * Removes the @a denom from the #denom_head DLL and re-insert its at the
    1306             :  * correct location sorted by next maintenance activity.
    1307             :  *
    1308             :  * @param[in,out] denom denomination to update material for
    1309             :  * @param now current time to use (to get many keys to use the exact same time)
    1310             :  * @param[in,out] wake set to true if we should wake the clients
    1311             :  * @return #GNUNET_OK on success
    1312             :  */
    1313             : static enum GNUNET_GenericReturnValue
    1314          96 : update_keys (struct Denomination *denom,
    1315             :              struct GNUNET_TIME_Timestamp now,
    1316             :              bool *wake)
    1317             : {
    1318             :   /* create new denomination keys */
    1319          96 :   if (NULL != denom->keys_tail)
    1320          23 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    1321             :                 "Updating keys of denomination `%s', last key %s valid for another %s\n",
    1322             :                 denom->section,
    1323             :                 GNUNET_h2s (&denom->keys_tail->h_rsa.hash),
    1324             :                 GNUNET_TIME_relative2s (
    1325             :                   GNUNET_TIME_absolute_get_remaining (
    1326             :                     GNUNET_TIME_absolute_subtract (
    1327             :                       GNUNET_TIME_absolute_add (
    1328             :                         denom->keys_tail->anchor.abs_time,
    1329             :                         denom->duration_withdraw),
    1330             :                       overlap_duration)),
    1331             :                   GNUNET_YES));
    1332        6401 :   while ( (NULL == denom->keys_tail) ||
    1333        3164 :           GNUNET_TIME_absolute_is_past (
    1334             :             GNUNET_TIME_absolute_subtract (
    1335             :               GNUNET_TIME_absolute_subtract (
    1336        3164 :                 GNUNET_TIME_absolute_add (denom->keys_tail->anchor.abs_time,
    1337             :                                           denom->duration_withdraw),
    1338             :                 lookahead_sign),
    1339             :               overlap_duration)) )
    1340             :   {
    1341        3141 :     if (! *wake)
    1342             :     {
    1343           1 :       key_gen++;
    1344           1 :       *wake = true;
    1345             :     }
    1346        3141 :     if (GNUNET_OK !=
    1347        3141 :         create_key (denom,
    1348             :                     now))
    1349             :     {
    1350           0 :       GNUNET_break (0);
    1351           0 :       globals->global_ret = EXIT_FAILURE;
    1352           0 :       GNUNET_SCHEDULER_shutdown ();
    1353           0 :       return GNUNET_SYSERR;
    1354             :     }
    1355             :   }
    1356             :   /* remove expired denomination keys */
    1357         194 :   while ( (NULL != denom->keys_head) &&
    1358          97 :           GNUNET_TIME_absolute_is_past
    1359          97 :             (GNUNET_TIME_absolute_add (denom->keys_head->anchor.abs_time,
    1360             :                                        denom->duration_withdraw)) )
    1361             :   {
    1362           1 :     struct DenominationKey *key = denom->keys_head;
    1363           1 :     struct DenominationKey *nxt = key->next;
    1364             : 
    1365           1 :     if (0 != key->rc)
    1366           0 :       break; /* later */
    1367           1 :     GNUNET_CONTAINER_DLL_remove (denom->keys_head,
    1368             :                                  denom->keys_tail,
    1369             :                                  key);
    1370           1 :     GNUNET_assert (GNUNET_OK ==
    1371             :                    GNUNET_CONTAINER_multihashmap_remove (
    1372             :                      keys,
    1373             :                      &key->h_rsa.hash,
    1374             :                      key));
    1375           2 :     if ( (! key->purge) &&
    1376           1 :          (0 != unlink (key->filename)) )
    1377           0 :       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
    1378             :                                 "unlink",
    1379             :                                 key->filename);
    1380           1 :     GNUNET_free (key->filename);
    1381           1 :     GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
    1382           1 :     GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
    1383           1 :     GNUNET_free (key->an);
    1384           1 :     GNUNET_free (key);
    1385           1 :     key = nxt;
    1386             :   }
    1387             : 
    1388             :   /* Update position of 'denom' in #denom_head DLL: sort by action time */
    1389             :   {
    1390             :     struct Denomination *before;
    1391             :     struct GNUNET_TIME_Absolute at;
    1392             : 
    1393          96 :     at = denomination_action_time (denom);
    1394          96 :     GNUNET_CONTAINER_DLL_remove (denom_head,
    1395             :                                  denom_tail,
    1396             :                                  denom);
    1397          96 :     before = NULL;
    1398          96 :     for (struct Denomination *pos = denom_head;
    1399          96 :          NULL != pos;
    1400           0 :          pos = pos->next)
    1401             :     {
    1402          76 :       if (GNUNET_TIME_absolute_cmp (denomination_action_time (pos),
    1403             :                                     >=,
    1404             :                                     at))
    1405          76 :         break;
    1406           0 :       before = pos;
    1407             :     }
    1408          96 :     GNUNET_CONTAINER_DLL_insert_after (denom_head,
    1409             :                                        denom_tail,
    1410             :                                        before,
    1411             :                                        denom);
    1412             :   }
    1413          96 :   return GNUNET_OK;
    1414             : }
    1415             : 
    1416             : 
    1417             : /**
    1418             :  * Task run periodically to expire keys and/or generate fresh ones.
    1419             :  *
    1420             :  * @param cls NULL
    1421             :  */
    1422             : static void
    1423          15 : update_denominations (void *cls)
    1424             : {
    1425             :   struct Denomination *denom;
    1426             :   struct GNUNET_TIME_Absolute now;
    1427             :   struct GNUNET_TIME_Timestamp t;
    1428          15 :   bool wake = false;
    1429             : 
    1430             :   (void) cls;
    1431          15 :   keygen_task = NULL;
    1432          15 :   now = GNUNET_TIME_absolute_get ();
    1433          15 :   t = GNUNET_TIME_absolute_to_timestamp (now);
    1434          15 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    1435             :               "Updating denominations ...\n");
    1436          15 :   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
    1437             :   do {
    1438          15 :     denom = denom_head;
    1439          15 :     if (GNUNET_OK !=
    1440          15 :         update_keys (denom,
    1441             :                      t,
    1442             :                      &wake))
    1443           0 :       return;
    1444          15 :   } while (denom != denom_head);
    1445          15 :   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
    1446          15 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    1447             :               "Updating denominations finished ...\n");
    1448          15 :   if (wake)
    1449           1 :     TES_wake_clients ();
    1450          15 :   keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
    1451             :                                          &update_denominations,
    1452             :                                          NULL);
    1453             : }
    1454             : 
    1455             : 
    1456             : /**
    1457             :  * Parse private key of denomination @a denom in @a buf.
    1458             :  *
    1459             :  * @param[out] denom denomination of the key
    1460             :  * @param filename name of the file we are parsing, for logging
    1461             :  * @param buf key material
    1462             :  * @param buf_size number of bytes in @a buf
    1463             :  */
    1464             : static void
    1465         424 : parse_key (struct Denomination *denom,
    1466             :            const char *filename,
    1467             :            const void *buf,
    1468             :            size_t buf_size)
    1469             : {
    1470             :   struct GNUNET_CRYPTO_RsaPrivateKey *priv;
    1471             :   char *anchor_s;
    1472             :   char dummy;
    1473             :   unsigned long long anchor_ll;
    1474             :   struct GNUNET_TIME_Timestamp anchor;
    1475             : 
    1476         424 :   anchor_s = strrchr (filename,
    1477             :                       '/');
    1478         424 :   if (NULL == anchor_s)
    1479             :   {
    1480             :     /* File in a directory without '/' in the name, this makes no sense. */
    1481           0 :     GNUNET_break (0);
    1482           0 :     return;
    1483             :   }
    1484         424 :   anchor_s++;
    1485         424 :   if (1 != sscanf (anchor_s,
    1486             :                    "%llu%c",
    1487             :                    &anchor_ll,
    1488             :                    &dummy))
    1489             :   {
    1490             :     /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */
    1491           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    1492             :                 "Filename `%s' invalid for key file, skipping\n",
    1493             :                 filename);
    1494           0 :     return;
    1495             :   }
    1496             :   anchor.abs_time.abs_value_us
    1497         424 :     = anchor_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
    1498         848 :   if (anchor_ll != anchor.abs_time.abs_value_us
    1499         424 :       / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
    1500             :   {
    1501             :     /* Integer overflow. Bad, invalid filename. */
    1502           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    1503             :                 "Filename `%s' invalid for key file, skipping\n",
    1504             :                 filename);
    1505           0 :     return;
    1506             :   }
    1507         424 :   priv = GNUNET_CRYPTO_rsa_private_key_decode (buf,
    1508             :                                                buf_size);
    1509         424 :   if (NULL == priv)
    1510             :   {
    1511             :     /* Parser failure. */
    1512           0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    1513             :                 "File `%s' is malformed, skipping\n",
    1514             :                 filename);
    1515           0 :     return;
    1516             :   }
    1517             : 
    1518             :   {
    1519             :     struct GNUNET_CRYPTO_RsaPublicKey *pub;
    1520             :     struct DenominationKey *dk;
    1521             :     struct DenominationKey *before;
    1522             : 
    1523         424 :     pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
    1524         424 :     if (NULL == pub)
    1525             :     {
    1526           0 :       GNUNET_break (0);
    1527           0 :       GNUNET_CRYPTO_rsa_private_key_free (priv);
    1528           0 :       return;
    1529             :     }
    1530         424 :     dk = GNUNET_new (struct DenominationKey);
    1531         424 :     dk->denom_priv = priv;
    1532         424 :     dk->denom = denom;
    1533         424 :     dk->anchor = anchor;
    1534         424 :     dk->filename = GNUNET_strdup (filename);
    1535         424 :     GNUNET_CRYPTO_rsa_public_key_hash (pub,
    1536             :                                        &dk->h_rsa.hash);
    1537         424 :     dk->denom_pub = pub;
    1538         424 :     generate_response (dk);
    1539         424 :     if (GNUNET_OK !=
    1540         424 :         GNUNET_CONTAINER_multihashmap_put (
    1541             :           keys,
    1542         424 :           &dk->h_rsa.hash,
    1543             :           dk,
    1544             :           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
    1545             :     {
    1546           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1547             :                   "Duplicate private key %s detected in file `%s'. Skipping.\n",
    1548             :                   GNUNET_h2s (&dk->h_rsa.hash),
    1549             :                   filename);
    1550           0 :       GNUNET_CRYPTO_rsa_private_key_free (priv);
    1551           0 :       GNUNET_CRYPTO_rsa_public_key_free (pub);
    1552           0 :       GNUNET_free (dk->an);
    1553           0 :       GNUNET_free (dk);
    1554           0 :       return;
    1555             :     }
    1556         424 :     before = NULL;
    1557         424 :     for (struct DenominationKey *pos = denom->keys_head;
    1558         424 :          NULL != pos;
    1559           0 :          pos = pos->next)
    1560             :     {
    1561         416 :       if (GNUNET_TIME_timestamp_cmp (pos->anchor,
    1562             :                                      >,
    1563             :                                      anchor))
    1564         416 :         break;
    1565           0 :       before = pos;
    1566             :     }
    1567         424 :     GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
    1568             :                                        denom->keys_tail,
    1569             :                                        before,
    1570             :                                        dk);
    1571         424 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    1572             :                 "Imported key %s from `%s'\n",
    1573             :                 GNUNET_h2s (&dk->h_rsa.hash),
    1574             :                 filename);
    1575             :   }
    1576             : }
    1577             : 
    1578             : 
    1579             : /**
    1580             :  * Import a private key from @a filename for the denomination
    1581             :  * given in @a cls.
    1582             :  *
    1583             :  * @param[in,out] cls a `struct Denomiantion`
    1584             :  * @param filename name of a file in the directory
    1585             :  * @return #GNUNET_OK (always, continue to iterate)
    1586             :  */
    1587             : static enum GNUNET_GenericReturnValue
    1588         424 : import_key (void *cls,
    1589             :             const char *filename)
    1590             : {
    1591         424 :   struct Denomination *denom = cls;
    1592             :   struct GNUNET_DISK_FileHandle *fh;
    1593             :   struct GNUNET_DISK_MapHandle *map;
    1594             :   void *ptr;
    1595             :   int fd;
    1596             :   struct stat sbuf;
    1597             : 
    1598             :   {
    1599             :     struct stat lsbuf;
    1600             : 
    1601         424 :     if (0 != lstat (filename,
    1602             :                     &lsbuf))
    1603             :     {
    1604           0 :       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    1605             :                                 "lstat",
    1606             :                                 filename);
    1607           0 :       return GNUNET_OK;
    1608             :     }
    1609         424 :     if (! S_ISREG (lsbuf.st_mode))
    1610             :     {
    1611           0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1612             :                   "File `%s' is not a regular file, which is not allowed for private keys!\n",
    1613             :                   filename);
    1614           0 :       return GNUNET_OK;
    1615             :     }
    1616             :   }
    1617             : 
    1618         424 :   fd = open (filename,
    1619             :              O_RDONLY | O_CLOEXEC);
    1620         424 :   if (-1 == fd)
    1621             :   {
    1622           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    1623             :                               "open",
    1624             :                               filename);
    1625           0 :     return GNUNET_OK;
    1626             :   }
    1627         424 :   if (0 != fstat (fd,
    1628             :                   &sbuf))
    1629             :   {
    1630           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    1631             :                               "stat",
    1632             :                               filename);
    1633           0 :     GNUNET_break (0 == close (fd));
    1634           0 :     return GNUNET_OK;
    1635             :   }
    1636         424 :   if (! S_ISREG (sbuf.st_mode))
    1637             :   {
    1638           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1639             :                 "File `%s' is not a regular file, which is not allowed for private keys!\n",
    1640             :                 filename);
    1641           0 :     GNUNET_break (0 == close (fd));
    1642           0 :     return GNUNET_OK;
    1643             :   }
    1644         424 :   if (0 != (sbuf.st_mode & (S_IWUSR | S_IRWXG | S_IRWXO)))
    1645             :   {
    1646             :     /* permission are NOT tight, try to patch them up! */
    1647           0 :     if (0 !=
    1648           0 :         fchmod (fd,
    1649             :                 S_IRUSR))
    1650             :     {
    1651           0 :       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    1652             :                                 "fchmod",
    1653             :                                 filename);
    1654             :       /* refuse to use key if file has wrong permissions */
    1655           0 :       GNUNET_break (0 == close (fd));
    1656           0 :       return GNUNET_OK;
    1657             :     }
    1658             :   }
    1659         424 :   fh = GNUNET_DISK_get_handle_from_int_fd (fd);
    1660         424 :   if (NULL == fh)
    1661             :   {
    1662           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    1663             :                               "open",
    1664             :                               filename);
    1665           0 :     GNUNET_break (0 == close (fd));
    1666           0 :     return GNUNET_OK;
    1667             :   }
    1668         424 :   if (sbuf.st_size > 16 * 1024)
    1669             :   {
    1670           0 :     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    1671             :                 "File `%s' too big to be a private key\n",
    1672             :                 filename);
    1673           0 :     GNUNET_DISK_file_close (fh);
    1674           0 :     return GNUNET_OK;
    1675             :   }
    1676         424 :   ptr = GNUNET_DISK_file_map (fh,
    1677             :                               &map,
    1678             :                               GNUNET_DISK_MAP_TYPE_READ,
    1679         424 :                               (size_t) sbuf.st_size);
    1680         424 :   if (NULL == ptr)
    1681             :   {
    1682           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    1683             :                               "mmap",
    1684             :                               filename);
    1685           0 :     GNUNET_DISK_file_close (fh);
    1686           0 :     return GNUNET_OK;
    1687             :   }
    1688         424 :   parse_key (denom,
    1689             :              filename,
    1690             :              ptr,
    1691         424 :              (size_t) sbuf.st_size);
    1692         424 :   GNUNET_DISK_file_unmap (map);
    1693         424 :   GNUNET_DISK_file_close (fh);
    1694         424 :   return GNUNET_OK;
    1695             : }
    1696             : 
    1697             : 
    1698             : /**
    1699             :  * Parse configuration for denomination type parameters.  Also determines
    1700             :  * our anchor by looking at the existing denominations of the same type.
    1701             :  *
    1702             :  * @param cfg configuration to use
    1703             :  * @param ct section in the configuration file giving the denomination type parameters
    1704             :  * @param[out] denom set to the denomination parameters from the configuration
    1705             :  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid
    1706             :  */
    1707             : static enum GNUNET_GenericReturnValue
    1708          81 : parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
    1709             :                         const char *ct,
    1710             :                         struct Denomination *denom)
    1711             : {
    1712             :   unsigned long long rsa_keysize;
    1713             :   char *secname;
    1714             : 
    1715          81 :   GNUNET_asprintf (&secname,
    1716             :                    "%s-secmod-rsa",
    1717          81 :                    globals->section);
    1718          81 :   if (GNUNET_OK !=
    1719          81 :       GNUNET_CONFIGURATION_get_value_time (cfg,
    1720             :                                            ct,
    1721             :                                            "DURATION_WITHDRAW",
    1722             :                                            &denom->duration_withdraw))
    1723             :   {
    1724           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    1725             :                                ct,
    1726             :                                "DURATION_WITHDRAW");
    1727           0 :     GNUNET_free (secname);
    1728           0 :     return GNUNET_SYSERR;
    1729             :   }
    1730          81 :   if (GNUNET_TIME_relative_cmp (overlap_duration,
    1731             :                                 >=,
    1732             :                                 denom->duration_withdraw))
    1733             :   {
    1734           0 :     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
    1735             :                                secname,
    1736             :                                "OVERLAP_DURATION",
    1737             :                                "Value given must be smaller than value for DURATION_WITHDRAW!");
    1738           0 :     GNUNET_free (secname);
    1739           0 :     return GNUNET_SYSERR;
    1740             :   }
    1741          81 :   if (GNUNET_OK !=
    1742          81 :       GNUNET_CONFIGURATION_get_value_number (cfg,
    1743             :                                              ct,
    1744             :                                              "RSA_KEYSIZE",
    1745             :                                              &rsa_keysize))
    1746             :   {
    1747           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    1748             :                                ct,
    1749             :                                "RSA_KEYSIZE");
    1750           0 :     GNUNET_free (secname);
    1751           0 :     return GNUNET_SYSERR;
    1752             :   }
    1753          81 :   if ( (rsa_keysize > 4 * 2048) ||
    1754          81 :        (rsa_keysize < 1024) )
    1755             :   {
    1756           0 :     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
    1757             :                                ct,
    1758             :                                "RSA_KEYSIZE",
    1759             :                                "Given RSA keysize outside of permitted range [1024,8192]\n");
    1760           0 :     GNUNET_free (secname);
    1761           0 :     return GNUNET_SYSERR;
    1762             :   }
    1763          81 :   GNUNET_free (secname);
    1764          81 :   denom->rsa_keysize = (unsigned int) rsa_keysize;
    1765          81 :   denom->section = GNUNET_strdup (ct);
    1766          81 :   return GNUNET_OK;
    1767             : }
    1768             : 
    1769             : 
    1770             : /**
    1771             :  * Closure for #load_denominations.
    1772             :  */
    1773             : struct LoadContext
    1774             : {
    1775             : 
    1776             :   /**
    1777             :    * Configuration to use.
    1778             :    */
    1779             :   const struct GNUNET_CONFIGURATION_Handle *cfg;
    1780             : 
    1781             :   /**
    1782             :    * Configuration section prefix to use for denomination settings.
    1783             :    * "coin_" for the exchange, "doco_" for Donau.
    1784             :    */
    1785             :   const char *cprefix;
    1786             : 
    1787             :   /**
    1788             :    * Current time to use.
    1789             :    */
    1790             :   struct GNUNET_TIME_Timestamp t;
    1791             : 
    1792             :   /**
    1793             :    * Status, to be set to #GNUNET_SYSERR on failure
    1794             :    */
    1795             :   enum GNUNET_GenericReturnValue ret;
    1796             : };
    1797             : 
    1798             : 
    1799             : /**
    1800             :  * Generate new denomination signing keys for the denomination type of the given @a
    1801             :  * denomination_alias.
    1802             :  *
    1803             :  * @param cls a `struct LoadContext`, with 'ret' to be set to #GNUNET_SYSERR on failure
    1804             :  * @param denomination_alias name of the denomination's section in the configuration
    1805             :  */
    1806             : static void
    1807         953 : load_denominations (void *cls,
    1808             :                     const char *denomination_alias)
    1809             : {
    1810         953 :   struct LoadContext *ctx = cls;
    1811             :   struct Denomination *denom;
    1812         953 :   bool wake = true;
    1813             :   char *cipher;
    1814             : 
    1815         953 :   if (0 != strncasecmp (denomination_alias,
    1816             :                         ctx->cprefix,
    1817             :                         strlen (ctx->cprefix)))
    1818         872 :     return; /* not a denomination type definition */
    1819         133 :   if (GNUNET_OK !=
    1820         133 :       GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
    1821             :                                              denomination_alias,
    1822             :                                              "CIPHER",
    1823             :                                              &cipher))
    1824             :   {
    1825           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    1826             :                                denomination_alias,
    1827             :                                "CIPHER");
    1828           0 :     return;
    1829             :   }
    1830         133 :   if (0 != strcmp (cipher, "RSA"))
    1831             :   {
    1832          52 :     GNUNET_free (cipher);
    1833          52 :     return; /* Ignore denominations of other types than CS */
    1834             :   }
    1835          81 :   GNUNET_free (cipher);
    1836          81 :   denom = GNUNET_new (struct Denomination);
    1837          81 :   if (GNUNET_OK !=
    1838          81 :       parse_denomination_cfg (ctx->cfg,
    1839             :                               denomination_alias,
    1840             :                               denom))
    1841             :   {
    1842           0 :     ctx->ret = GNUNET_SYSERR;
    1843           0 :     GNUNET_free (denom);
    1844           0 :     return;
    1845             :   }
    1846          81 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    1847             :               "Loading keys for denomination %s\n",
    1848             :               denom->section);
    1849             :   {
    1850             :     char *dname;
    1851             : 
    1852          81 :     GNUNET_asprintf (&dname,
    1853             :                      "%s/%s",
    1854             :                      keydir,
    1855             :                      denom->section);
    1856          81 :     GNUNET_break (GNUNET_OK ==
    1857             :                   GNUNET_DISK_directory_create (dname));
    1858          81 :     GNUNET_DISK_directory_scan (dname,
    1859             :                                 &import_key,
    1860             :                                 denom);
    1861          81 :     GNUNET_free (dname);
    1862             :   }
    1863          81 :   GNUNET_CONTAINER_DLL_insert (denom_head,
    1864             :                                denom_tail,
    1865             :                                denom);
    1866          81 :   update_keys (denom,
    1867             :                ctx->t,
    1868             :                &wake);
    1869             : }
    1870             : 
    1871             : 
    1872             : /**
    1873             :  * Load the various duration values from @a cfg
    1874             :  *
    1875             :  * @param cfg configuration to use
    1876             :  * @return #GNUNET_OK on success
    1877             :  */
    1878             : static enum GNUNET_GenericReturnValue
    1879          20 : load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg)
    1880             : {
    1881             :   char *secname;
    1882             : 
    1883          20 :   GNUNET_asprintf (&secname,
    1884             :                    "%s-secmod-rsa",
    1885          20 :                    globals->section);
    1886          20 :   if (GNUNET_OK !=
    1887          20 :       GNUNET_CONFIGURATION_get_value_time (cfg,
    1888             :                                            secname,
    1889             :                                            "OVERLAP_DURATION",
    1890             :                                            &overlap_duration))
    1891             :   {
    1892           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    1893             :                                secname,
    1894             :                                "OVERLAP_DURATION");
    1895           0 :     GNUNET_free (secname);
    1896           0 :     return GNUNET_SYSERR;
    1897             :   }
    1898          20 :   if (GNUNET_OK !=
    1899          20 :       GNUNET_CONFIGURATION_get_value_time (cfg,
    1900             :                                            secname,
    1901             :                                            "LOOKAHEAD_SIGN",
    1902             :                                            &lookahead_sign))
    1903             :   {
    1904           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    1905             :                                secname,
    1906             :                                "LOOKAHEAD_SIGN");
    1907           0 :     GNUNET_free (secname);
    1908           0 :     return GNUNET_SYSERR;
    1909             :   }
    1910          20 :   GNUNET_free (secname);
    1911          20 :   return GNUNET_OK;
    1912             : }
    1913             : 
    1914             : 
    1915             : /**
    1916             :  * Function run on shutdown. Stops the various jobs (nicely).
    1917             :  *
    1918             :  * @param cls NULL
    1919             :  */
    1920             : static void
    1921          20 : do_shutdown (void *cls)
    1922             : {
    1923             :   (void) cls;
    1924          20 :   TES_listen_stop ();
    1925          20 :   if (NULL != keygen_task)
    1926             :   {
    1927          13 :     GNUNET_SCHEDULER_cancel (keygen_task);
    1928          13 :     keygen_task = NULL;
    1929             :   }
    1930          20 :   stop_workers ();
    1931          20 :   sem_done (&worker_sem);
    1932          20 : }
    1933             : 
    1934             : 
    1935             : void
    1936          20 : TALER_SECMOD_rsa_run (void *cls,
    1937             :                       char *const *args,
    1938             :                       const char *cfgfile,
    1939             :                       const struct GNUNET_CONFIGURATION_Handle *cfg)
    1940             : {
    1941             :   static struct TES_Callbacks cb = {
    1942             :     .dispatch = rsa_work_dispatch,
    1943             :     .updater = rsa_update_client_keys,
    1944             :     .init = rsa_client_init
    1945             :   };
    1946          20 :   struct TALER_SECMOD_Options *opt = cls;
    1947             :   char *secname;
    1948             : 
    1949             :   (void) args;
    1950             :   (void) cfgfile;
    1951          20 :   globals = opt;
    1952          20 :   if (GNUNET_TIME_timestamp_cmp (opt->global_now,
    1953             :                                  !=,
    1954             :                                  opt->global_now_tmp))
    1955             :   {
    1956             :     /* The user gave "--now", use it! */
    1957           0 :     opt->global_now = opt->global_now_tmp;
    1958             :   }
    1959             :   else
    1960             :   {
    1961             :     /* get current time again, we may be timetraveling! */
    1962          20 :     opt->global_now = GNUNET_TIME_timestamp_get ();
    1963             :   }
    1964          20 :   GNUNET_asprintf (&secname,
    1965             :                    "%s-secmod-rsa",
    1966             :                    opt->section);
    1967          20 :   if (GNUNET_OK !=
    1968          20 :       GNUNET_CONFIGURATION_get_value_filename (cfg,
    1969             :                                                secname,
    1970             :                                                "KEY_DIR",
    1971             :                                                &keydir))
    1972             :   {
    1973           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    1974             :                                secname,
    1975             :                                "KEY_DIR");
    1976           0 :     GNUNET_free (secname);
    1977           0 :     opt->global_ret = EXIT_NOTCONFIGURED;
    1978           7 :     return;
    1979             :   }
    1980          20 :   if (GNUNET_OK !=
    1981          20 :       load_durations (cfg))
    1982             :   {
    1983           0 :     opt->global_ret = EXIT_NOTCONFIGURED;
    1984           0 :     GNUNET_free (secname);
    1985           0 :     return;
    1986             :   }
    1987          20 :   opt->global_ret = TES_listen_start (cfg,
    1988             :                                       secname,
    1989             :                                       &cb);
    1990          20 :   GNUNET_free (secname);
    1991          20 :   if (0 != opt->global_ret)
    1992           0 :     return;
    1993          20 :   sem_init (&worker_sem,
    1994             :             0);
    1995          20 :   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
    1996             :                                  NULL);
    1997          20 :   if (0 == opt->max_workers)
    1998             :   {
    1999             :     long lret;
    2000             : 
    2001           0 :     lret = sysconf (_SC_NPROCESSORS_CONF);
    2002           0 :     if (lret <= 0)
    2003           0 :       lret = 1;
    2004           0 :     opt->max_workers = (unsigned int) lret;
    2005             :   }
    2006             : 
    2007         340 :   for (unsigned int i = 0; i<opt->max_workers; i++)
    2008         320 :     if (GNUNET_OK !=
    2009         320 :         start_worker ())
    2010             :     {
    2011           0 :       GNUNET_SCHEDULER_shutdown ();
    2012           0 :       return;
    2013             :     }
    2014             :   /* Load denominations */
    2015          20 :   keys = GNUNET_CONTAINER_multihashmap_create (65536,
    2016             :                                                true);
    2017             :   {
    2018          20 :     struct LoadContext lc = {
    2019             :       .cfg = cfg,
    2020             :       .ret = GNUNET_OK,
    2021             :       .t = opt->global_now,
    2022          20 :       .cprefix = opt->cprefix
    2023             :     };
    2024             : 
    2025          20 :     GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
    2026          20 :     GNUNET_CONFIGURATION_iterate_sections (cfg,
    2027             :                                            &load_denominations,
    2028             :                                            &lc);
    2029          20 :     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
    2030          20 :     if (GNUNET_OK != lc.ret)
    2031             :     {
    2032           0 :       opt->global_ret = EXIT_FAILURE;
    2033           0 :       GNUNET_SCHEDULER_shutdown ();
    2034           0 :       return;
    2035             :     }
    2036             :   }
    2037          20 :   if (NULL == denom_head)
    2038             :   {
    2039           7 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    2040             :                 "No RSA denominations configured. Make sure section names start with `%s' if you are using RSA!\n",
    2041             :                 opt->section);
    2042           7 :     TES_wake_clients ();
    2043           7 :     return;
    2044             :   }
    2045             :   /* start job to keep keys up-to-date; MUST be run before the #listen_task,
    2046             :      hence with priority. */
    2047          13 :   keygen_task = GNUNET_SCHEDULER_add_with_priority (
    2048             :     GNUNET_SCHEDULER_PRIORITY_URGENT,
    2049             :     &update_denominations,
    2050             :     NULL);
    2051             : }

Generated by: LCOV version 1.16