exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

secmod_rsa.c (60485B)


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