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 (60585B)


      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   bool failure = false;
    752 
    753   if (bs > TALER_MAX_COINS)
    754   {
    755     GNUNET_break_op (0);
    756     return GNUNET_SYSERR;
    757   }
    758   {
    759     struct BatchJob jobs[bs];
    760 
    761     while ( (idx < bs) &&
    762             (size > sizeof (struct TALER_CRYPTO_SignRequest)) )
    763     {
    764       const struct TALER_CRYPTO_SignRequest *sr = off;
    765       uint16_t s = ntohs (sr->header.size);
    766 
    767       if ( (s > size) ||
    768            (s < sizeof (*sr)) )
    769       {
    770         failure = true;
    771         bs = idx;
    772         break;
    773       }
    774       start_job (sr,
    775                  &jobs[idx++]);
    776       off += s;
    777       size -= s;
    778     }
    779     GNUNET_break_op (0 == size);
    780     bs = GNUNET_MIN (bs,
    781                      idx);
    782     for (unsigned int i = 0; i<bs; i++)
    783       finish_job (client,
    784                   &jobs[i]);
    785   }
    786   if (failure)
    787   {
    788     struct TALER_CRYPTO_SignFailure sf = {
    789       .header.size = htons (sizeof (sf)),
    790       .header.type = htons (TALER_HELPER_RSA_MT_RES_BATCH_FAILURE),
    791       .ec = htonl (TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE)
    792     };
    793 
    794     GNUNET_break (0);
    795     return TES_transmit (client->csock,
    796                          &sf.header);
    797   }
    798   return GNUNET_OK;
    799 }
    800 
    801 
    802 /**
    803  * Start worker thread for batch processing.
    804  *
    805  * @return #GNUNET_OK on success
    806  */
    807 static enum GNUNET_GenericReturnValue
    808 start_worker (void)
    809 {
    810   struct Worker *w;
    811 
    812   w = GNUNET_new (struct Worker);
    813   sem_init (&w->sem,
    814             0);
    815   if (0 != pthread_create (&w->pt,
    816                            NULL,
    817                            &worker,
    818                            w))
    819   {
    820     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
    821                          "pthread_create");
    822     GNUNET_free (w);
    823     return GNUNET_SYSERR;
    824   }
    825   workers++;
    826   return GNUNET_OK;
    827 }
    828 
    829 
    830 /**
    831  * Stop all worker threads.
    832  */
    833 static void
    834 stop_workers (void)
    835 {
    836   while (workers > 0)
    837   {
    838     struct Worker *w;
    839     void *result;
    840 
    841     sem_down (&worker_sem);
    842     GNUNET_assert (0 == pthread_mutex_lock (&worker_lock));
    843     w = worker_head;
    844     GNUNET_CONTAINER_DLL_remove (worker_head,
    845                                  worker_tail,
    846                                  w);
    847     GNUNET_assert (0 == pthread_mutex_unlock (&worker_lock));
    848     w->do_shutdown = true;
    849     sem_up (&w->sem);
    850     pthread_join (w->pt,
    851                   &result);
    852     GNUNET_assert (result == w);
    853     sem_done (&w->sem);
    854     GNUNET_free (w);
    855     workers--;
    856   }
    857 }
    858 
    859 
    860 /**
    861  * Initialize key material for denomination key @a dk (also on disk).
    862  *
    863  * @param[in,out] dk denomination key to compute key material for
    864  * @param position where in the DLL will the @a dk go
    865  * @return #GNUNET_OK on success
    866  */
    867 static enum GNUNET_GenericReturnValue
    868 setup_key (struct DenominationKey *dk,
    869            struct DenominationKey *position)
    870 {
    871   struct Denomination *denom = dk->denom;
    872   struct GNUNET_CRYPTO_RsaPrivateKey *priv;
    873   struct GNUNET_CRYPTO_RsaPublicKey *pub;
    874   size_t buf_size;
    875   void *buf;
    876 
    877   priv = GNUNET_CRYPTO_rsa_private_key_create (denom->rsa_keysize);
    878   if (NULL == priv)
    879   {
    880     GNUNET_break (0);
    881     GNUNET_SCHEDULER_shutdown ();
    882     globals->global_ret = EXIT_FAILURE;
    883     return GNUNET_SYSERR;
    884   }
    885   pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
    886   if (NULL == pub)
    887   {
    888     GNUNET_break (0);
    889     GNUNET_CRYPTO_rsa_private_key_free (priv);
    890     return GNUNET_SYSERR;
    891   }
    892   buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
    893                                                    &buf);
    894   GNUNET_CRYPTO_rsa_public_key_hash (pub,
    895                                      &dk->h_rsa.hash);
    896   GNUNET_asprintf (
    897     &dk->filename,
    898     "%s/%s/%llu-%llu",
    899     keydir,
    900     denom->section,
    901     (unsigned long long) (dk->anchor_start.abs_time.abs_value_us
    902                           / GNUNET_TIME_UNIT_SECONDS.rel_value_us),
    903     (unsigned long long) (dk->anchor_end.abs_time.abs_value_us
    904                           / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
    905   if (GNUNET_OK !=
    906       GNUNET_DISK_fn_write (dk->filename,
    907                             buf,
    908                             buf_size,
    909                             GNUNET_DISK_PERM_USER_READ))
    910   {
    911     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
    912                               "write",
    913                               dk->filename);
    914     GNUNET_free (dk->filename);
    915     GNUNET_free (buf);
    916     GNUNET_CRYPTO_rsa_private_key_free (priv);
    917     GNUNET_CRYPTO_rsa_public_key_free (pub);
    918     return GNUNET_SYSERR;
    919   }
    920   GNUNET_free (buf);
    921   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    922               "Setup fresh private key %s at %s in `%s' (generation #%llu)\n",
    923               GNUNET_h2s (&dk->h_rsa.hash),
    924               GNUNET_TIME_timestamp2s (dk->anchor_start),
    925               dk->filename,
    926               (unsigned long long) key_gen);
    927   dk->denom_priv = priv;
    928   dk->denom_pub = pub;
    929   dk->key_gen = key_gen;
    930   generate_response (dk);
    931   if (GNUNET_OK !=
    932       GNUNET_CONTAINER_multihashmap_put (
    933         keys,
    934         &dk->h_rsa.hash,
    935         dk,
    936         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
    937   {
    938     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    939                 "Duplicate private key created! Terminating.\n");
    940     GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
    941     GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
    942     GNUNET_free (dk->filename);
    943     GNUNET_free (dk->an);
    944     GNUNET_free (dk);
    945     return GNUNET_SYSERR;
    946   }
    947   GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
    948                                      denom->keys_tail,
    949                                      position,
    950                                      dk);
    951   return GNUNET_OK;
    952 }
    953 
    954 
    955 /**
    956  * The withdraw period of a key @a dk has expired. Purge it.
    957  *
    958  * @param[in] dk expired denomination key to purge
    959  */
    960 static void
    961 purge_key (struct DenominationKey *dk)
    962 {
    963   if (dk->purge)
    964     return;
    965   if (0 != unlink (dk->filename))
    966     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
    967                               "unlink",
    968                               dk->filename);
    969   GNUNET_free (dk->filename);
    970   dk->purge = true;
    971   dk->key_gen = key_gen;
    972 }
    973 
    974 
    975 /**
    976  * A @a client informs us that a key has been revoked.
    977  * Check if the key is still in use, and if so replace (!)
    978  * it with a fresh key.
    979  *
    980  * @param client the client making the request
    981  * @param rr the revocation request
    982  */
    983 static enum GNUNET_GenericReturnValue
    984 handle_revoke_request (struct TES_Client *client,
    985                        const struct TALER_CRYPTO_RevokeRequest *rr)
    986 {
    987   struct DenominationKey *dk;
    988   struct DenominationKey *ndk;
    989   struct Denomination *denom;
    990 
    991   (void) client;
    992   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
    993   dk = GNUNET_CONTAINER_multihashmap_get (keys,
    994                                           &rr->h_rsa.hash);
    995   if (NULL == dk)
    996   {
    997     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
    998     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    999                 "Revocation request ignored, denomination key %s unknown\n",
   1000                 GNUNET_h2s (&rr->h_rsa.hash));
   1001     return GNUNET_OK;
   1002   }
   1003   if (dk->purge)
   1004   {
   1005     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1006     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1007                 "Revocation request ignored, denomination key %s already revoked\n",
   1008                 GNUNET_h2s (&rr->h_rsa.hash));
   1009     return GNUNET_OK;
   1010   }
   1011 
   1012   key_gen++;
   1013   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1014               "Revoking key %s, bumping generation to %llu\n",
   1015               GNUNET_h2s (&rr->h_rsa.hash),
   1016               (unsigned long long) key_gen);
   1017   purge_key (dk);
   1018 
   1019   /* Setup replacement key */
   1020   denom = dk->denom;
   1021   ndk = GNUNET_new (struct DenominationKey);
   1022   ndk->denom = denom;
   1023   ndk->anchor_start = dk->anchor_start;
   1024   ndk->anchor_end = dk->anchor_end;
   1025   if (GNUNET_OK !=
   1026       setup_key (ndk,
   1027                  dk))
   1028   {
   1029     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1030     GNUNET_break (0);
   1031     GNUNET_SCHEDULER_shutdown ();
   1032     globals->global_ret = EXIT_FAILURE;
   1033     return GNUNET_SYSERR;
   1034   }
   1035   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1036   TES_wake_clients ();
   1037   return GNUNET_OK;
   1038 }
   1039 
   1040 
   1041 /**
   1042  * Handle @a hdr message received from @a client.
   1043  *
   1044  * @param client the client that received the message
   1045  * @param hdr message that was received
   1046  * @return #GNUNET_OK on success
   1047  */
   1048 static enum GNUNET_GenericReturnValue
   1049 rsa_work_dispatch (struct TES_Client *client,
   1050                    const struct GNUNET_MessageHeader *hdr)
   1051 {
   1052   uint16_t msize = ntohs (hdr->size);
   1053 
   1054   switch (ntohs (hdr->type))
   1055   {
   1056   case TALER_HELPER_RSA_MT_REQ_SIGN:
   1057     if (msize <= sizeof (struct TALER_CRYPTO_SignRequest))
   1058     {
   1059       GNUNET_break_op (0);
   1060       return GNUNET_SYSERR;
   1061     }
   1062     return handle_sign_request (
   1063       client,
   1064       (const struct TALER_CRYPTO_SignRequest *) hdr);
   1065   case TALER_HELPER_RSA_MT_REQ_REVOKE:
   1066     if (msize != sizeof (struct TALER_CRYPTO_RevokeRequest))
   1067     {
   1068       GNUNET_break_op (0);
   1069       return GNUNET_SYSERR;
   1070     }
   1071     return handle_revoke_request (
   1072       client,
   1073       (const struct TALER_CRYPTO_RevokeRequest *) hdr);
   1074   case TALER_HELPER_RSA_MT_REQ_BATCH_SIGN:
   1075     if (msize <= sizeof (struct TALER_CRYPTO_BatchSignRequest))
   1076     {
   1077       GNUNET_break_op (0);
   1078       return GNUNET_SYSERR;
   1079     }
   1080     return handle_batch_sign_request (
   1081       client,
   1082       (const struct TALER_CRYPTO_BatchSignRequest *) hdr);
   1083   default:
   1084     GNUNET_break_op (0);
   1085     return GNUNET_SYSERR;
   1086   }
   1087 }
   1088 
   1089 
   1090 /**
   1091  * Send our initial key set to @a client together with the
   1092  * "sync" terminator.
   1093  *
   1094  * @param client the client to inform
   1095  * @return #GNUNET_OK on success
   1096  */
   1097 static enum GNUNET_GenericReturnValue
   1098 rsa_client_init (struct TES_Client *client)
   1099 {
   1100   size_t obs = 0;
   1101   char *buf;
   1102 
   1103   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1104               "Initializing new client %p\n",
   1105               client);
   1106   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   1107   for (struct Denomination *denom = denom_head;
   1108        NULL != denom;
   1109        denom = denom->next)
   1110   {
   1111     for (struct DenominationKey *dk = denom->keys_head;
   1112          NULL != dk;
   1113          dk = dk->next)
   1114     {
   1115       GNUNET_assert (obs + ntohs (dk->an->header.size)
   1116                      > obs);
   1117       obs += ntohs (dk->an->header.size);
   1118     }
   1119   }
   1120   buf = GNUNET_malloc (obs);
   1121   obs = 0;
   1122   for (struct Denomination *denom = denom_head;
   1123        NULL != denom;
   1124        denom = denom->next)
   1125   {
   1126     for (struct DenominationKey *dk = denom->keys_head;
   1127          NULL != dk;
   1128          dk = dk->next)
   1129     {
   1130       GNUNET_memcpy (&buf[obs],
   1131                      dk->an,
   1132                      ntohs (dk->an->header.size));
   1133       GNUNET_assert (obs + ntohs (dk->an->header.size)
   1134                      > obs);
   1135       obs += ntohs (dk->an->header.size);
   1136     }
   1137   }
   1138   client->key_gen = key_gen;
   1139   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1140   if (GNUNET_OK !=
   1141       TES_transmit_raw (client->csock,
   1142                         obs,
   1143                         buf))
   1144   {
   1145     GNUNET_free (buf);
   1146     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1147                 "Client %p must have disconnected\n",
   1148                 client);
   1149     return GNUNET_SYSERR;
   1150   }
   1151   GNUNET_free (buf);
   1152   {
   1153     struct GNUNET_MessageHeader synced = {
   1154       .type = htons (TALER_HELPER_RSA_SYNCED),
   1155       .size = htons (sizeof (synced))
   1156     };
   1157 
   1158     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1159                 "Sending RSA SYNCED message to %p\n",
   1160                 client);
   1161     if (GNUNET_OK !=
   1162         TES_transmit (client->csock,
   1163                       &synced))
   1164     {
   1165       GNUNET_break (0);
   1166       return GNUNET_SYSERR;
   1167     }
   1168   }
   1169   return GNUNET_OK;
   1170 }
   1171 
   1172 
   1173 /**
   1174  * Notify @a client about all changes to the keys since
   1175  * the last generation known to the @a client.
   1176  *
   1177  * @param client the client to notify
   1178  * @return #GNUNET_OK on success
   1179  */
   1180 static enum GNUNET_GenericReturnValue
   1181 rsa_update_client_keys (struct TES_Client *client)
   1182 {
   1183   size_t obs = 0;
   1184   char *buf;
   1185   enum GNUNET_GenericReturnValue ret;
   1186 
   1187   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   1188   for (struct Denomination *denom = denom_head;
   1189        NULL != denom;
   1190        denom = denom->next)
   1191   {
   1192     for (struct DenominationKey *key = denom->keys_head;
   1193          NULL != key;
   1194          key = key->next)
   1195     {
   1196       if (key->key_gen <= client->key_gen)
   1197         continue;
   1198       if (key->purge)
   1199         obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification);
   1200       else
   1201         obs += ntohs (key->an->header.size);
   1202     }
   1203   }
   1204   if (0 == obs)
   1205   {
   1206     /* nothing to do */
   1207     client->key_gen = key_gen;
   1208     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1209     return GNUNET_OK;
   1210   }
   1211   buf = GNUNET_malloc (obs);
   1212   obs = 0;
   1213   for (struct Denomination *denom = denom_head;
   1214        NULL != denom;
   1215        denom = denom->next)
   1216   {
   1217     for (struct DenominationKey *key = denom->keys_head;
   1218          NULL != key;
   1219          key = key->next)
   1220     {
   1221       if (key->key_gen <= client->key_gen)
   1222         continue;
   1223       if (key->purge)
   1224       {
   1225         struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
   1226           .header.type = htons (TALER_HELPER_RSA_MT_PURGE),
   1227           .header.size = htons (sizeof (pn)),
   1228           .h_rsa = key->h_rsa
   1229         };
   1230 
   1231         GNUNET_memcpy (&buf[obs],
   1232                        &pn,
   1233                        sizeof (pn));
   1234         GNUNET_assert (obs + sizeof (pn)
   1235                        > obs);
   1236         obs += sizeof (pn);
   1237       }
   1238       else
   1239       {
   1240         GNUNET_memcpy (&buf[obs],
   1241                        key->an,
   1242                        ntohs (key->an->header.size));
   1243         GNUNET_assert (obs + ntohs (key->an->header.size)
   1244                        > obs);
   1245         obs += ntohs (key->an->header.size);
   1246       }
   1247     }
   1248   }
   1249   client->key_gen = key_gen;
   1250   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1251   ret = TES_transmit_raw (client->csock,
   1252                           obs,
   1253                           buf);
   1254   GNUNET_free (buf);
   1255   return ret;
   1256 }
   1257 
   1258 
   1259 /**
   1260  * Create a new denomination key (we do not have enough).
   1261  *
   1262  * @param[in,out] denom denomination key to create
   1263  * @param anchor_start when to start key signing validity
   1264  * @param anchor_end when to end key signing validity
   1265  * @return #GNUNET_OK on success
   1266  */
   1267 static enum GNUNET_GenericReturnValue
   1268 create_key (struct Denomination *denom,
   1269             struct GNUNET_TIME_Timestamp anchor_start,
   1270             struct GNUNET_TIME_Timestamp anchor_end)
   1271 {
   1272   struct DenominationKey *dk;
   1273 
   1274   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1275               "Creating new key for `%s' with start date %s\n",
   1276               denom->section,
   1277               GNUNET_TIME_timestamp2s (anchor_start));
   1278   dk = GNUNET_new (struct DenominationKey);
   1279   dk->denom = denom;
   1280   dk->anchor_start = anchor_start;
   1281   dk->anchor_end = anchor_end;
   1282   if (GNUNET_OK !=
   1283       setup_key (dk,
   1284                  denom->keys_tail))
   1285   {
   1286     GNUNET_break (0);
   1287     GNUNET_free (dk);
   1288     GNUNET_SCHEDULER_shutdown ();
   1289     globals->global_ret = EXIT_FAILURE;
   1290     return GNUNET_SYSERR;
   1291   }
   1292   return GNUNET_OK;
   1293 }
   1294 
   1295 
   1296 /**
   1297  * Obtain the maximum withdraw duration of all denominations.
   1298  *
   1299  * Must only be called while the #keys_lock is held.
   1300  *
   1301  * @return maximum withdraw duration, zero if there are no denominations
   1302  */
   1303 static struct GNUNET_TIME_Relative
   1304 get_maximum_duration (void)
   1305 {
   1306   struct GNUNET_TIME_Relative ret
   1307     = GNUNET_TIME_UNIT_ZERO;
   1308 
   1309   for (struct Denomination *denom = denom_head;
   1310        NULL != denom;
   1311        denom = denom->next)
   1312   {
   1313     ret = GNUNET_TIME_relative_max (ret,
   1314                                     denom->duration_withdraw);
   1315   }
   1316   return ret;
   1317 }
   1318 
   1319 
   1320 /**
   1321  * At what time do we need to next create keys if we just did?
   1322  *
   1323  * @return time when to next create keys if we just finished key generation
   1324  */
   1325 static struct GNUNET_TIME_Absolute
   1326 action_time (void)
   1327 {
   1328   struct GNUNET_TIME_Relative md = get_maximum_duration ();
   1329   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   1330   uint64_t mod;
   1331 
   1332   if (GNUNET_TIME_relative_is_zero (md))
   1333     return GNUNET_TIME_UNIT_FOREVER_ABS;
   1334   mod = now.abs_value_us % md.rel_value_us;
   1335   now.abs_value_us -= mod;
   1336   return GNUNET_TIME_absolute_add (now,
   1337                                    md);
   1338 }
   1339 
   1340 
   1341 /**
   1342  * Remove all denomination keys of @a denom that have expired.
   1343  *
   1344  * @param[in,out] denom denomination family to remove keys for
   1345  */
   1346 static void
   1347 remove_expired_denomination_keys (struct Denomination *denom)
   1348 {
   1349   while ( (NULL != denom->keys_head) &&
   1350           GNUNET_TIME_absolute_is_past (
   1351             denom->keys_head->anchor_end.abs_time))
   1352   {
   1353     struct DenominationKey *key = denom->keys_head;
   1354     struct DenominationKey *nxt = key->next;
   1355 
   1356     if (0 != key->rc)
   1357       break; /* later */
   1358     GNUNET_CONTAINER_DLL_remove (denom->keys_head,
   1359                                  denom->keys_tail,
   1360                                  key);
   1361     GNUNET_assert (GNUNET_OK ==
   1362                    GNUNET_CONTAINER_multihashmap_remove (
   1363                      keys,
   1364                      &key->h_rsa.hash,
   1365                      key));
   1366     if ( (! key->purge) &&
   1367          (0 != unlink (key->filename)) )
   1368       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR,
   1369                                 "unlink",
   1370                                 key->filename);
   1371     GNUNET_free (key->filename);
   1372     GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
   1373     GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
   1374     GNUNET_free (key->an);
   1375     GNUNET_free (key);
   1376     key = nxt;
   1377   }
   1378 }
   1379 
   1380 
   1381 /**
   1382  * Obtain the end anchor to use at this point. Uses the
   1383  * #lookahead_sign and then rounds it up by the maximum
   1384  * duration of any denomination to arrive at a globally
   1385  * valid end-date.
   1386  *
   1387  * Must only be called while the #keys_lock is held.
   1388  *
   1389  * @return end anchor
   1390  */
   1391 static struct GNUNET_TIME_Timestamp
   1392 get_anchor_end (void)
   1393 {
   1394   struct GNUNET_TIME_Relative md = get_maximum_duration ();
   1395   struct GNUNET_TIME_Absolute end
   1396     = GNUNET_TIME_relative_to_absolute (lookahead_sign);
   1397   uint64_t mod;
   1398 
   1399   if (GNUNET_TIME_relative_is_zero (md))
   1400     return GNUNET_TIME_UNIT_ZERO_TS;
   1401   /* Round up 'end' to a multiple of 'md' */
   1402   mod = end.abs_value_us % md.rel_value_us;
   1403   end.abs_value_us -= mod;
   1404   return GNUNET_TIME_absolute_to_timestamp (
   1405     GNUNET_TIME_absolute_add (end,
   1406                               md));
   1407 }
   1408 
   1409 
   1410 /**
   1411  * Create all denomination keys that are required for our
   1412  * desired lookahead and that we do not yet have.
   1413  *
   1414  * @param[in,out] opt our options
   1415  * @param[in,out] wake set to true if we should wake the clients
   1416  */
   1417 static void
   1418 create_missing_keys (struct TALER_SECMOD_Options *opt,
   1419                      bool *wake)
   1420 {
   1421   struct GNUNET_TIME_Timestamp start;
   1422   struct GNUNET_TIME_Timestamp end;
   1423 
   1424   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1425               "Updating denominations ...\n");
   1426   start = opt->global_now;
   1427   GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   1428   end = get_anchor_end ();
   1429   for (struct Denomination *denom = denom_head;
   1430        NULL != denom;
   1431        denom = denom->next)
   1432   {
   1433     struct GNUNET_TIME_Timestamp anchor_start;
   1434     struct GNUNET_TIME_Timestamp anchor_end;
   1435     struct GNUNET_TIME_Timestamp next_end;
   1436     bool finished = false;
   1437 
   1438     remove_expired_denomination_keys (denom);
   1439     if (NULL != denom->keys_tail)
   1440     {
   1441       anchor_start = denom->keys_tail->anchor_end;
   1442       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1443                   "Expanding keys of denomination `%s', last key %s valid for another %s\n",
   1444                   denom->section,
   1445                   GNUNET_h2s (&denom->keys_tail->h_rsa.hash),
   1446                   GNUNET_TIME_relative2s (
   1447                     GNUNET_TIME_absolute_get_remaining (
   1448                       anchor_start.abs_time),
   1449                     true));
   1450     }
   1451     else
   1452     {
   1453       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1454                   "Starting keys of denomination `%s'\n",
   1455                   denom->section);
   1456       anchor_start = start;
   1457     }
   1458     finished = GNUNET_TIME_timestamp_cmp (anchor_start,
   1459                                           >=,
   1460                                           end);
   1461     while (! finished)
   1462     {
   1463       anchor_end = GNUNET_TIME_absolute_to_timestamp (
   1464         GNUNET_TIME_absolute_add (anchor_start.abs_time,
   1465                                   denom->duration_withdraw));
   1466       next_end = GNUNET_TIME_absolute_to_timestamp (
   1467         GNUNET_TIME_absolute_add (anchor_end.abs_time,
   1468                                   denom->duration_withdraw));
   1469       if (GNUNET_TIME_timestamp_cmp (next_end,
   1470                                      >,
   1471                                      end))
   1472       {
   1473         anchor_end = end; /* extend period to align end periods */
   1474         finished = true;
   1475       }
   1476       /* adjust start time down to ensure overlap */
   1477       anchor_start = GNUNET_TIME_absolute_to_timestamp (
   1478         GNUNET_TIME_absolute_subtract (anchor_start.abs_time,
   1479                                        overlap_duration));
   1480       if (! *wake)
   1481       {
   1482         key_gen++;
   1483         *wake = true;
   1484       }
   1485       if (GNUNET_OK !=
   1486           create_key (denom,
   1487                       anchor_start,
   1488                       anchor_end))
   1489       {
   1490         GNUNET_break (0);
   1491         GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1492         globals->global_ret = EXIT_FAILURE;
   1493         GNUNET_SCHEDULER_shutdown ();
   1494         return;
   1495       }
   1496       anchor_start = anchor_end;
   1497     }
   1498     remove_expired_denomination_keys (denom);
   1499   }
   1500   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1501   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1502               "Updating denominations finished ...\n");
   1503 }
   1504 
   1505 
   1506 /**
   1507  * Task run periodically to expire keys and/or generate fresh ones.
   1508  *
   1509  * @param cls the `struct TALER_SECMOD_Options *`
   1510  */
   1511 static void
   1512 update_denominations (void *cls)
   1513 {
   1514   struct TALER_SECMOD_Options *opt = cls;
   1515   struct GNUNET_TIME_Absolute at;
   1516   bool wake = false;
   1517 
   1518   (void) cls;
   1519   keygen_task = NULL;
   1520   /* update current time, global override no longer applies */
   1521   opt->global_now = GNUNET_TIME_timestamp_get ();
   1522   create_missing_keys (opt,
   1523                        &wake);
   1524   if (wake)
   1525     TES_wake_clients ();
   1526   at = action_time ();
   1527   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1528               "Next key generation due at %s\n",
   1529               GNUNET_TIME_absolute2s (at));
   1530   keygen_task = GNUNET_SCHEDULER_add_at (at,
   1531                                          &update_denominations,
   1532                                          opt);
   1533 }
   1534 
   1535 
   1536 /**
   1537  * Parse private key of denomination @a denom in @a buf.
   1538  *
   1539  * @param[out] denom denomination of the key
   1540  * @param filename name of the file we are parsing, for logging
   1541  * @param buf key material
   1542  * @param buf_size number of bytes in @a buf
   1543  */
   1544 static void
   1545 parse_key (struct Denomination *denom,
   1546            const char *filename,
   1547            const void *buf,
   1548            size_t buf_size)
   1549 {
   1550   struct GNUNET_CRYPTO_RsaPrivateKey *priv;
   1551   const char *anchor_s;
   1552   char dummy;
   1553   unsigned long long anchor_start_ll;
   1554   unsigned long long anchor_end_ll;
   1555   struct GNUNET_TIME_Timestamp anchor_start;
   1556   struct GNUNET_TIME_Timestamp anchor_end;
   1557   char *nf = NULL;
   1558 
   1559   anchor_s = strrchr (filename,
   1560                       '/');
   1561   if (NULL == anchor_s)
   1562   {
   1563     /* File in a directory without '/' in the name, this makes no sense. */
   1564     GNUNET_break (0);
   1565     return;
   1566   }
   1567   anchor_s++;
   1568   if (2 != sscanf (anchor_s,
   1569                    "%llu-%llu%c",
   1570                    &anchor_start_ll,
   1571                    &anchor_end_ll,
   1572                    &dummy))
   1573   {
   1574     /* try legacy mode */
   1575     if (1 != sscanf (anchor_s,
   1576                      "%llu%c",
   1577                      &anchor_start_ll,
   1578                      &dummy))
   1579     {
   1580       /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */
   1581       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1582                   "Filename `%s' invalid for key file, skipping\n",
   1583                   anchor_s);
   1584       return;
   1585     }
   1586     anchor_start.abs_time.abs_value_us
   1587       = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
   1588     if (anchor_start_ll != anchor_start.abs_time.abs_value_us
   1589         / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
   1590     {
   1591       /* Integer overflow. Bad, invalid filename. */
   1592       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1593                   "Integer overflow. Filename `%s' invalid for key file, skipping\n",
   1594                   anchor_s);
   1595       return;
   1596     }
   1597     anchor_end
   1598       = GNUNET_TIME_absolute_to_timestamp (
   1599           GNUNET_TIME_absolute_add (anchor_start.abs_time,
   1600                                     denom->duration_withdraw));
   1601     GNUNET_asprintf (
   1602       &nf,
   1603       "%s/%s/%llu-%llu",
   1604       keydir,
   1605       denom->section,
   1606       anchor_start_ll,
   1607       (unsigned long long) (anchor_end.abs_time.abs_value_us
   1608                             / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
   1609     /* Try to fix the legacy filename */
   1610     if (0 !=
   1611         rename (filename,
   1612                 nf))
   1613     {
   1614       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1615                                 "rename",
   1616                                 filename);
   1617       GNUNET_free (nf);
   1618     }
   1619   }
   1620   else
   1621   {
   1622     anchor_start.abs_time.abs_value_us
   1623       = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
   1624     anchor_end.abs_time.abs_value_us
   1625       = anchor_end_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
   1626     if ( (anchor_start_ll != anchor_start.abs_time.abs_value_us
   1627           / GNUNET_TIME_UNIT_SECONDS.rel_value_us) ||
   1628          (anchor_end_ll != anchor_end.abs_time.abs_value_us
   1629           / GNUNET_TIME_UNIT_SECONDS.rel_value_us) )
   1630     {
   1631       /* Integer overflow. Bad, invalid filename. */
   1632       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1633                   "Integer overflow. Filename `%s' invalid for key file, skipping\n",
   1634                   anchor_s);
   1635       return;
   1636     }
   1637   }
   1638   priv = GNUNET_CRYPTO_rsa_private_key_decode (buf,
   1639                                                buf_size);
   1640   if (NULL == priv)
   1641   {
   1642     /* Parser failure. */
   1643     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1644                 "File `%s' is malformed, skipping\n",
   1645                 (NULL == nf) ? filename : nf);
   1646     GNUNET_free (nf);
   1647     return;
   1648   }
   1649 
   1650   {
   1651     struct GNUNET_CRYPTO_RsaPublicKey *pub;
   1652     struct DenominationKey *dk;
   1653     struct DenominationKey *before;
   1654 
   1655     pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
   1656     if (NULL == pub)
   1657     {
   1658       GNUNET_break (0);
   1659       GNUNET_CRYPTO_rsa_private_key_free (priv);
   1660       GNUNET_free (nf);
   1661       return;
   1662     }
   1663     dk = GNUNET_new (struct DenominationKey);
   1664     dk->denom_priv = priv;
   1665     dk->denom = denom;
   1666     dk->anchor_start = anchor_start;
   1667     dk->anchor_end = anchor_end;
   1668     dk->filename = (NULL == nf) ? GNUNET_strdup (filename) : nf;
   1669     GNUNET_CRYPTO_rsa_public_key_hash (pub,
   1670                                        &dk->h_rsa.hash);
   1671     dk->denom_pub = pub;
   1672     generate_response (dk);
   1673     if (GNUNET_OK !=
   1674         GNUNET_CONTAINER_multihashmap_put (
   1675           keys,
   1676           &dk->h_rsa.hash,
   1677           dk,
   1678           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
   1679     {
   1680       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1681                   "Duplicate private key %s detected in file `%s'. Skipping.\n",
   1682                   GNUNET_h2s (&dk->h_rsa.hash),
   1683                   filename);
   1684       GNUNET_CRYPTO_rsa_private_key_free (priv);
   1685       GNUNET_CRYPTO_rsa_public_key_free (pub);
   1686       GNUNET_free (dk->an);
   1687       GNUNET_free (dk);
   1688       return;
   1689     }
   1690     before = NULL;
   1691     for (struct DenominationKey *pos = denom->keys_head;
   1692          NULL != pos;
   1693          pos = pos->next)
   1694     {
   1695       if (GNUNET_TIME_timestamp_cmp (pos->anchor_start,
   1696                                      >,
   1697                                      anchor_start))
   1698         break;
   1699       before = pos;
   1700     }
   1701     GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
   1702                                        denom->keys_tail,
   1703                                        before,
   1704                                        dk);
   1705     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1706                 "Imported key %s from `%s'\n",
   1707                 GNUNET_h2s (&dk->h_rsa.hash),
   1708                 filename);
   1709   }
   1710 }
   1711 
   1712 
   1713 /**
   1714  * Import a private key from @a filename for the denomination
   1715  * given in @a cls.
   1716  *
   1717  * @param[in,out] cls a `struct Denomiantion`
   1718  * @param filename name of a file in the directory
   1719  * @return #GNUNET_OK (always, continue to iterate)
   1720  */
   1721 static enum GNUNET_GenericReturnValue
   1722 import_key (void *cls,
   1723             const char *filename)
   1724 {
   1725   struct Denomination *denom = cls;
   1726   struct GNUNET_DISK_FileHandle *fh;
   1727   struct GNUNET_DISK_MapHandle *map;
   1728   void *ptr;
   1729   int fd;
   1730   struct stat sbuf;
   1731 
   1732   {
   1733     struct stat lsbuf;
   1734 
   1735     if (0 != lstat (filename,
   1736                     &lsbuf))
   1737     {
   1738       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1739                                 "lstat",
   1740                                 filename);
   1741       return GNUNET_OK;
   1742     }
   1743     if (! S_ISREG (lsbuf.st_mode))
   1744     {
   1745       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1746                   "File `%s' is not a regular file, which is not allowed for private keys!\n",
   1747                   filename);
   1748       return GNUNET_OK;
   1749     }
   1750   }
   1751 
   1752   fd = open (filename,
   1753              O_RDONLY | O_CLOEXEC);
   1754   if (-1 == fd)
   1755   {
   1756     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1757                               "open",
   1758                               filename);
   1759     return GNUNET_OK;
   1760   }
   1761   if (0 != fstat (fd,
   1762                   &sbuf))
   1763   {
   1764     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1765                               "stat",
   1766                               filename);
   1767     GNUNET_break (0 == close (fd));
   1768     return GNUNET_OK;
   1769   }
   1770   if (! S_ISREG (sbuf.st_mode))
   1771   {
   1772     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1773                 "File `%s' is not a regular file, which is not allowed for private keys!\n",
   1774                 filename);
   1775     GNUNET_break (0 == close (fd));
   1776     return GNUNET_OK;
   1777   }
   1778   if (0 != (sbuf.st_mode & (S_IWUSR | S_IRWXG | S_IRWXO)))
   1779   {
   1780     /* permission are NOT tight, try to patch them up! */
   1781     if (0 !=
   1782         fchmod (fd,
   1783                 S_IRUSR))
   1784     {
   1785       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1786                                 "fchmod",
   1787                                 filename);
   1788       /* refuse to use key if file has wrong permissions */
   1789       GNUNET_break (0 == close (fd));
   1790       return GNUNET_OK;
   1791     }
   1792   }
   1793   fh = GNUNET_DISK_get_handle_from_int_fd (fd);
   1794   if (NULL == fh)
   1795   {
   1796     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1797                               "open",
   1798                               filename);
   1799     GNUNET_break (0 == close (fd));
   1800     return GNUNET_OK;
   1801   }
   1802   if (sbuf.st_size > 16 * 1024)
   1803   {
   1804     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1805                 "File `%s' too big to be a private key\n",
   1806                 filename);
   1807     GNUNET_DISK_file_close (fh);
   1808     return GNUNET_OK;
   1809   }
   1810   ptr = GNUNET_DISK_file_map (fh,
   1811                               &map,
   1812                               GNUNET_DISK_MAP_TYPE_READ,
   1813                               (size_t) sbuf.st_size);
   1814   if (NULL == ptr)
   1815   {
   1816     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1817                               "mmap",
   1818                               filename);
   1819     GNUNET_DISK_file_close (fh);
   1820     return GNUNET_OK;
   1821   }
   1822   parse_key (denom,
   1823              filename,
   1824              ptr,
   1825              (size_t) sbuf.st_size);
   1826   GNUNET_DISK_file_unmap (map);
   1827   GNUNET_DISK_file_close (fh);
   1828   return GNUNET_OK;
   1829 }
   1830 
   1831 
   1832 /**
   1833  * Parse configuration for denomination type parameters.  Also determines
   1834  * our anchor by looking at the existing denominations of the same type.
   1835  *
   1836  * @param cfg configuration to use
   1837  * @param ct section in the configuration file giving the denomination type parameters
   1838  * @param[out] denom set to the denomination parameters from the configuration
   1839  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid
   1840  */
   1841 static enum GNUNET_GenericReturnValue
   1842 parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
   1843                         const char *ct,
   1844                         struct Denomination *denom)
   1845 {
   1846   unsigned long long rsa_keysize;
   1847   char *secname;
   1848 
   1849   GNUNET_asprintf (&secname,
   1850                    "%s-secmod-rsa",
   1851                    globals->section);
   1852   if (GNUNET_OK !=
   1853       GNUNET_CONFIGURATION_get_value_time (cfg,
   1854                                            ct,
   1855                                            "DURATION_WITHDRAW",
   1856                                            &denom->duration_withdraw))
   1857   {
   1858     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1859                                ct,
   1860                                "DURATION_WITHDRAW");
   1861     GNUNET_free (secname);
   1862     return GNUNET_SYSERR;
   1863   }
   1864   if (GNUNET_TIME_relative_cmp (denom->duration_withdraw,
   1865                                 <,
   1866                                 GNUNET_TIME_UNIT_SECONDS))
   1867   {
   1868     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   1869                                ct,
   1870                                "DURATION_WITHDRAW",
   1871                                "less than one second is not supported");
   1872     GNUNET_free (secname);
   1873     return GNUNET_SYSERR;
   1874   }
   1875   if (GNUNET_TIME_relative_cmp (overlap_duration,
   1876                                 >=,
   1877                                 denom->duration_withdraw))
   1878   {
   1879     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   1880                                secname,
   1881                                "OVERLAP_DURATION",
   1882                                "Value given must be smaller than value for DURATION_WITHDRAW!");
   1883     GNUNET_free (secname);
   1884     return GNUNET_SYSERR;
   1885   }
   1886   if (GNUNET_OK !=
   1887       GNUNET_CONFIGURATION_get_value_number (cfg,
   1888                                              ct,
   1889                                              "RSA_KEYSIZE",
   1890                                              &rsa_keysize))
   1891   {
   1892     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1893                                ct,
   1894                                "RSA_KEYSIZE");
   1895     GNUNET_free (secname);
   1896     return GNUNET_SYSERR;
   1897   }
   1898   if ( (rsa_keysize > 4 * 2048) ||
   1899        (rsa_keysize < 1024) )
   1900   {
   1901     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   1902                                ct,
   1903                                "RSA_KEYSIZE",
   1904                                "Given RSA keysize outside of permitted range [1024,8192]\n");
   1905     GNUNET_free (secname);
   1906     return GNUNET_SYSERR;
   1907   }
   1908   GNUNET_free (secname);
   1909   denom->rsa_keysize = (unsigned int) rsa_keysize;
   1910   denom->section = GNUNET_strdup (ct);
   1911   return GNUNET_OK;
   1912 }
   1913 
   1914 
   1915 /**
   1916  * Closure for #load_denominations.
   1917  */
   1918 struct LoadContext
   1919 {
   1920 
   1921   /**
   1922    * Configuration to use.
   1923    */
   1924   const struct GNUNET_CONFIGURATION_Handle *cfg;
   1925 
   1926   /**
   1927    * Configuration section prefix to use for denomination settings.
   1928    * "coin_" for the exchange, "doco_" for Donau.
   1929    */
   1930   const char *cprefix;
   1931 
   1932   /**
   1933    * Status, to be set to #GNUNET_SYSERR on failure
   1934    */
   1935   enum GNUNET_GenericReturnValue ret;
   1936 };
   1937 
   1938 
   1939 /**
   1940  * Generate new denomination signing keys for the denomination type of the given @a
   1941  * denomination_alias.
   1942  *
   1943  * @param cls a `struct LoadContext`, with 'ret' to be set to #GNUNET_SYSERR on failure
   1944  * @param denomination_alias name of the denomination's section in the configuration
   1945  */
   1946 static void
   1947 load_denominations (void *cls,
   1948                     const char *denomination_alias)
   1949 {
   1950   struct LoadContext *ctx = cls;
   1951   struct Denomination *denom;
   1952   char *cipher;
   1953 
   1954   if (0 != strncasecmp (denomination_alias,
   1955                         ctx->cprefix,
   1956                         strlen (ctx->cprefix)))
   1957     return; /* not a denomination type definition */
   1958   if (GNUNET_OK !=
   1959       GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
   1960                                              denomination_alias,
   1961                                              "CIPHER",
   1962                                              &cipher))
   1963   {
   1964     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1965                                denomination_alias,
   1966                                "CIPHER");
   1967     return;
   1968   }
   1969   if (0 != strcmp (cipher,
   1970                    "RSA"))
   1971   {
   1972     GNUNET_free (cipher);
   1973     return; /* Ignore denominations of other types than CS */
   1974   }
   1975   GNUNET_free (cipher);
   1976   denom = GNUNET_new (struct Denomination);
   1977   if (GNUNET_OK !=
   1978       parse_denomination_cfg (ctx->cfg,
   1979                               denomination_alias,
   1980                               denom))
   1981   {
   1982     ctx->ret = GNUNET_SYSERR;
   1983     GNUNET_free (denom);
   1984     return;
   1985   }
   1986   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1987               "Loading keys for denomination %s\n",
   1988               denom->section);
   1989   {
   1990     char *dname;
   1991 
   1992     GNUNET_asprintf (&dname,
   1993                      "%s/%s",
   1994                      keydir,
   1995                      denom->section);
   1996     GNUNET_break (GNUNET_OK ==
   1997                   GNUNET_DISK_directory_create (dname));
   1998     GNUNET_DISK_directory_scan (dname,
   1999                                 &import_key,
   2000                                 denom);
   2001     GNUNET_free (dname);
   2002   }
   2003   GNUNET_CONTAINER_DLL_insert (denom_head,
   2004                                denom_tail,
   2005                                denom);
   2006 }
   2007 
   2008 
   2009 /**
   2010  * Load the various duration values from @a cfg
   2011  *
   2012  * @param cfg configuration to use
   2013  * @return #GNUNET_OK on success
   2014  */
   2015 static enum GNUNET_GenericReturnValue
   2016 load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg)
   2017 {
   2018   char *secname;
   2019 
   2020   GNUNET_asprintf (&secname,
   2021                    "%s-secmod-rsa",
   2022                    globals->section);
   2023   if (GNUNET_OK !=
   2024       GNUNET_CONFIGURATION_get_value_time (cfg,
   2025                                            secname,
   2026                                            "OVERLAP_DURATION",
   2027                                            &overlap_duration))
   2028   {
   2029     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2030                                secname,
   2031                                "OVERLAP_DURATION");
   2032     GNUNET_free (secname);
   2033     return GNUNET_SYSERR;
   2034   }
   2035   if (GNUNET_OK !=
   2036       GNUNET_CONFIGURATION_get_value_time (cfg,
   2037                                            secname,
   2038                                            "LOOKAHEAD_SIGN",
   2039                                            &lookahead_sign))
   2040   {
   2041     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2042                                secname,
   2043                                "LOOKAHEAD_SIGN");
   2044     GNUNET_free (secname);
   2045     return GNUNET_SYSERR;
   2046   }
   2047   GNUNET_free (secname);
   2048   return GNUNET_OK;
   2049 }
   2050 
   2051 
   2052 /**
   2053  * Function run on shutdown. Stops the various jobs (nicely).
   2054  *
   2055  * @param cls NULL
   2056  */
   2057 static void
   2058 do_shutdown (void *cls)
   2059 {
   2060   (void) cls;
   2061   TES_listen_stop ();
   2062   if (NULL != keygen_task)
   2063   {
   2064     GNUNET_SCHEDULER_cancel (keygen_task);
   2065     keygen_task = NULL;
   2066   }
   2067   stop_workers ();
   2068   sem_done (&worker_sem);
   2069 }
   2070 
   2071 
   2072 void
   2073 TALER_SECMOD_rsa_run (void *cls,
   2074                       char *const *args,
   2075                       const char *cfgfile,
   2076                       const struct GNUNET_CONFIGURATION_Handle *cfg)
   2077 {
   2078   static struct TES_Callbacks cb = {
   2079     .dispatch = rsa_work_dispatch,
   2080     .updater = rsa_update_client_keys,
   2081     .init = rsa_client_init
   2082   };
   2083   struct TALER_SECMOD_Options *opt = cls;
   2084   char *secname;
   2085 
   2086   (void) args;
   2087   (void) cfgfile;
   2088   globals = opt;
   2089   if (GNUNET_TIME_timestamp_cmp (opt->global_now,
   2090                                  !=,
   2091                                  opt->global_now_tmp))
   2092   {
   2093     /* The user gave "--now", use it! */
   2094     opt->global_now = opt->global_now_tmp;
   2095   }
   2096   else
   2097   {
   2098     /* get current time again, we may be timetraveling! */
   2099     opt->global_now = GNUNET_TIME_timestamp_get ();
   2100   }
   2101   GNUNET_asprintf (&secname,
   2102                    "%s-secmod-rsa",
   2103                    opt->section);
   2104   if (GNUNET_OK !=
   2105       GNUNET_CONFIGURATION_get_value_filename (cfg,
   2106                                                secname,
   2107                                                "KEY_DIR",
   2108                                                &keydir))
   2109   {
   2110     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2111                                secname,
   2112                                "KEY_DIR");
   2113     GNUNET_free (secname);
   2114     opt->global_ret = EXIT_NOTCONFIGURED;
   2115     return;
   2116   }
   2117   if (GNUNET_OK !=
   2118       load_durations (cfg))
   2119   {
   2120     opt->global_ret = EXIT_NOTCONFIGURED;
   2121     GNUNET_free (secname);
   2122     return;
   2123   }
   2124   opt->global_ret = TES_listen_start (cfg,
   2125                                       secname,
   2126                                       &cb);
   2127   GNUNET_free (secname);
   2128   if (0 != opt->global_ret)
   2129     return;
   2130   sem_init (&worker_sem,
   2131             0);
   2132   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
   2133                                  NULL);
   2134   if (0 == opt->max_workers)
   2135   {
   2136     long lret;
   2137 
   2138     lret = sysconf (_SC_NPROCESSORS_CONF);
   2139     if (lret <= 0)
   2140       lret = 1;
   2141     opt->max_workers = (unsigned int) lret;
   2142   }
   2143 
   2144   for (unsigned int i = 0; i<opt->max_workers; i++)
   2145     if (GNUNET_OK !=
   2146         start_worker ())
   2147     {
   2148       GNUNET_SCHEDULER_shutdown ();
   2149       return;
   2150     }
   2151   /* Load denominations */
   2152   keys = GNUNET_CONTAINER_multihashmap_create (65536,
   2153                                                true);
   2154   {
   2155     struct LoadContext lc = {
   2156       .cfg = cfg,
   2157       .ret = GNUNET_OK,
   2158       .cprefix = opt->cprefix
   2159     };
   2160     bool wake = true;
   2161 
   2162     GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   2163     GNUNET_CONFIGURATION_iterate_sections (cfg,
   2164                                            &load_denominations,
   2165                                            &lc);
   2166     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   2167     if (GNUNET_OK != lc.ret)
   2168     {
   2169       opt->global_ret = EXIT_FAILURE;
   2170       GNUNET_SCHEDULER_shutdown ();
   2171       return;
   2172     }
   2173     create_missing_keys (opt,
   2174                          &wake);
   2175   }
   2176   if (NULL == denom_head)
   2177   {
   2178     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2179                 "No RSA denominations configured. Make sure section names start with `%s' if you are using RSA!\n",
   2180                 opt->cprefix);
   2181     TES_wake_clients ();
   2182     return;
   2183   }
   2184   /* start job to keep keys up-to-date; MUST be run before the #listen_task,
   2185      hence with priority. */
   2186   keygen_task = GNUNET_SCHEDULER_add_with_priority (
   2187     GNUNET_SCHEDULER_PRIORITY_URGENT,
   2188     &update_denominations,
   2189     opt);
   2190 }