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


      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 "taler/platform.h"
     35 #include "taler/taler_util.h"
     36 #include "secmod_rsa.h"
     37 #include <gcrypt.h>
     38 #include <pthread.h>
     39 #include "taler/taler_error_codes.h"
     40 #include "taler/taler_signatures.h"
     41 #include "secmod_common.h"
     42 #include <poll.h>
     43 
     44 
     45 /**
     46  * Information we keep per denomination.
     47  */
     48 struct Denomination;
     49 
     50 
     51 /**
     52  * One particular denomination key.
     53  */
     54 struct DenominationKey
     55 {
     56 
     57   /**
     58    * Kept in a DLL of the respective denomination. Sorted by anchor time.
     59    */
     60   struct DenominationKey *next;
     61 
     62   /**
     63    * Kept in a DLL of the respective denomination. Sorted by anchor time.
     64    */
     65   struct DenominationKey *prev;
     66 
     67   /**
     68    * Denomination this key belongs to.
     69    */
     70   struct Denomination *denom;
     71 
     72   /**
     73    * Name of the file this key is stored under.
     74    */
     75   char *filename;
     76 
     77   /**
     78    * The private key of the denomination.
     79    */
     80   struct GNUNET_CRYPTO_RsaPrivateKey *denom_priv;
     81 
     82   /**
     83    * The public key of the denomination.
     84    */
     85   struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
     86 
     87   /**
     88    * Message to transmit to clients to introduce this public key.
     89    */
     90   struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
     91 
     92   /**
     93    * Hash of this denomination's public key.
     94    */
     95   struct TALER_RsaPubHashP h_rsa;
     96 
     97   /**
     98    * Time at which this key is supposed to become valid.
     99    */
    100   struct GNUNET_TIME_Timestamp anchor_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         return;
   1488       }
   1489       anchor_start = anchor_end;
   1490     }
   1491     remove_expired_denomination_keys (denom);
   1492   }
   1493   GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   1494   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1495               "Updating denominations finished ...\n");
   1496 }
   1497 
   1498 
   1499 /**
   1500  * Task run periodically to expire keys and/or generate fresh ones.
   1501  *
   1502  * @param cls the `struct TALER_SECMOD_Options *`
   1503  */
   1504 static void
   1505 update_denominations (void *cls)
   1506 {
   1507   struct TALER_SECMOD_Options *opt = cls;
   1508   struct GNUNET_TIME_Absolute at;
   1509   bool wake = false;
   1510 
   1511   (void) cls;
   1512   keygen_task = NULL;
   1513   /* update current time, global override no longer applies */
   1514   opt->global_now = GNUNET_TIME_timestamp_get ();
   1515   create_missing_keys (opt,
   1516                        &wake);
   1517   if (wake)
   1518     TES_wake_clients ();
   1519   at = action_time ();
   1520   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1521               "Next key generation due at %s\n",
   1522               GNUNET_TIME_absolute2s (at));
   1523   keygen_task = GNUNET_SCHEDULER_add_at (at,
   1524                                          &update_denominations,
   1525                                          opt);
   1526 }
   1527 
   1528 
   1529 /**
   1530  * Parse private key of denomination @a denom in @a buf.
   1531  *
   1532  * @param[out] denom denomination of the key
   1533  * @param filename name of the file we are parsing, for logging
   1534  * @param buf key material
   1535  * @param buf_size number of bytes in @a buf
   1536  */
   1537 static void
   1538 parse_key (struct Denomination *denom,
   1539            const char *filename,
   1540            const void *buf,
   1541            size_t buf_size)
   1542 {
   1543   struct GNUNET_CRYPTO_RsaPrivateKey *priv;
   1544   char *anchor_s;
   1545   char dummy;
   1546   unsigned long long anchor_start_ll;
   1547   unsigned long long anchor_end_ll;
   1548   struct GNUNET_TIME_Timestamp anchor_start;
   1549   struct GNUNET_TIME_Timestamp anchor_end;
   1550   char *nf = NULL;
   1551 
   1552   anchor_s = strrchr (filename,
   1553                       '/');
   1554   if (NULL == anchor_s)
   1555   {
   1556     /* File in a directory without '/' in the name, this makes no sense. */
   1557     GNUNET_break (0);
   1558     return;
   1559   }
   1560   anchor_s++;
   1561   if (2 != sscanf (anchor_s,
   1562                    "%llu-%llu%c",
   1563                    &anchor_start_ll,
   1564                    &anchor_end_ll,
   1565                    &dummy))
   1566   {
   1567     /* try legacy mode */
   1568     if (1 != sscanf (anchor_s,
   1569                      "%llu%c",
   1570                      &anchor_start_ll,
   1571                      &dummy))
   1572     {
   1573       /* Filenames in KEYDIR must ONLY be the anchor time in seconds! */
   1574       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1575                   "Filename `%s' invalid for key file, skipping\n",
   1576                   anchor_s);
   1577       return;
   1578     }
   1579     anchor_start.abs_time.abs_value_us
   1580       = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
   1581     if (anchor_start_ll != anchor_start.abs_time.abs_value_us
   1582         / GNUNET_TIME_UNIT_SECONDS.rel_value_us)
   1583     {
   1584       /* Integer overflow. Bad, invalid filename. */
   1585       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1586                   "Integer overflow. Filename `%s' invalid for key file, skipping\n",
   1587                   anchor_s);
   1588       return;
   1589     }
   1590     anchor_end
   1591       = GNUNET_TIME_absolute_to_timestamp (
   1592           GNUNET_TIME_absolute_add (anchor_start.abs_time,
   1593                                     denom->duration_withdraw));
   1594     GNUNET_asprintf (
   1595       &nf,
   1596       "%s/%s/%llu-%llu",
   1597       keydir,
   1598       denom->section,
   1599       anchor_start_ll,
   1600       (unsigned long long) (anchor_end.abs_time.abs_value_us
   1601                             / GNUNET_TIME_UNIT_SECONDS.rel_value_us));
   1602     /* Try to fix the legacy filename */
   1603     if (0 !=
   1604         rename (filename,
   1605                 nf))
   1606     {
   1607       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1608                                 "rename",
   1609                                 filename);
   1610       GNUNET_free (nf);
   1611     }
   1612   }
   1613   else
   1614   {
   1615     anchor_start.abs_time.abs_value_us
   1616       = anchor_start_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
   1617     anchor_end.abs_time.abs_value_us
   1618       = anchor_end_ll * GNUNET_TIME_UNIT_SECONDS.rel_value_us;
   1619     if ( (anchor_start_ll != anchor_start.abs_time.abs_value_us
   1620           / GNUNET_TIME_UNIT_SECONDS.rel_value_us) ||
   1621          (anchor_end_ll != anchor_end.abs_time.abs_value_us
   1622           / GNUNET_TIME_UNIT_SECONDS.rel_value_us) )
   1623     {
   1624       /* Integer overflow. Bad, invalid filename. */
   1625       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1626                   "Integer overflow. Filename `%s' invalid for key file, skipping\n",
   1627                   anchor_s);
   1628       return;
   1629     }
   1630   }
   1631   priv = GNUNET_CRYPTO_rsa_private_key_decode (buf,
   1632                                                buf_size);
   1633   if (NULL == priv)
   1634   {
   1635     /* Parser failure. */
   1636     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1637                 "File `%s' is malformed, skipping\n",
   1638                 (NULL == nf) ? filename : nf);
   1639     GNUNET_free (nf);
   1640     return;
   1641   }
   1642 
   1643   {
   1644     struct GNUNET_CRYPTO_RsaPublicKey *pub;
   1645     struct DenominationKey *dk;
   1646     struct DenominationKey *before;
   1647 
   1648     pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
   1649     if (NULL == pub)
   1650     {
   1651       GNUNET_break (0);
   1652       GNUNET_CRYPTO_rsa_private_key_free (priv);
   1653       GNUNET_free (nf);
   1654       return;
   1655     }
   1656     dk = GNUNET_new (struct DenominationKey);
   1657     dk->denom_priv = priv;
   1658     dk->denom = denom;
   1659     dk->anchor_start = anchor_start;
   1660     dk->anchor_end = anchor_end;
   1661     dk->filename = (NULL == nf) ? GNUNET_strdup (filename) : nf;
   1662     GNUNET_CRYPTO_rsa_public_key_hash (pub,
   1663                                        &dk->h_rsa.hash);
   1664     dk->denom_pub = pub;
   1665     generate_response (dk);
   1666     if (GNUNET_OK !=
   1667         GNUNET_CONTAINER_multihashmap_put (
   1668           keys,
   1669           &dk->h_rsa.hash,
   1670           dk,
   1671           GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
   1672     {
   1673       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1674                   "Duplicate private key %s detected in file `%s'. Skipping.\n",
   1675                   GNUNET_h2s (&dk->h_rsa.hash),
   1676                   filename);
   1677       GNUNET_CRYPTO_rsa_private_key_free (priv);
   1678       GNUNET_CRYPTO_rsa_public_key_free (pub);
   1679       GNUNET_free (dk->an);
   1680       GNUNET_free (dk);
   1681       return;
   1682     }
   1683     before = NULL;
   1684     for (struct DenominationKey *pos = denom->keys_head;
   1685          NULL != pos;
   1686          pos = pos->next)
   1687     {
   1688       if (GNUNET_TIME_timestamp_cmp (pos->anchor_start,
   1689                                      >,
   1690                                      anchor_start))
   1691         break;
   1692       before = pos;
   1693     }
   1694     GNUNET_CONTAINER_DLL_insert_after (denom->keys_head,
   1695                                        denom->keys_tail,
   1696                                        before,
   1697                                        dk);
   1698     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1699                 "Imported key %s from `%s'\n",
   1700                 GNUNET_h2s (&dk->h_rsa.hash),
   1701                 filename);
   1702   }
   1703 }
   1704 
   1705 
   1706 /**
   1707  * Import a private key from @a filename for the denomination
   1708  * given in @a cls.
   1709  *
   1710  * @param[in,out] cls a `struct Denomiantion`
   1711  * @param filename name of a file in the directory
   1712  * @return #GNUNET_OK (always, continue to iterate)
   1713  */
   1714 static enum GNUNET_GenericReturnValue
   1715 import_key (void *cls,
   1716             const char *filename)
   1717 {
   1718   struct Denomination *denom = cls;
   1719   struct GNUNET_DISK_FileHandle *fh;
   1720   struct GNUNET_DISK_MapHandle *map;
   1721   void *ptr;
   1722   int fd;
   1723   struct stat sbuf;
   1724 
   1725   {
   1726     struct stat lsbuf;
   1727 
   1728     if (0 != lstat (filename,
   1729                     &lsbuf))
   1730     {
   1731       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1732                                 "lstat",
   1733                                 filename);
   1734       return GNUNET_OK;
   1735     }
   1736     if (! S_ISREG (lsbuf.st_mode))
   1737     {
   1738       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1739                   "File `%s' is not a regular file, which is not allowed for private keys!\n",
   1740                   filename);
   1741       return GNUNET_OK;
   1742     }
   1743   }
   1744 
   1745   fd = open (filename,
   1746              O_RDONLY | O_CLOEXEC);
   1747   if (-1 == fd)
   1748   {
   1749     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1750                               "open",
   1751                               filename);
   1752     return GNUNET_OK;
   1753   }
   1754   if (0 != fstat (fd,
   1755                   &sbuf))
   1756   {
   1757     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1758                               "stat",
   1759                               filename);
   1760     GNUNET_break (0 == close (fd));
   1761     return GNUNET_OK;
   1762   }
   1763   if (! S_ISREG (sbuf.st_mode))
   1764   {
   1765     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1766                 "File `%s' is not a regular file, which is not allowed for private keys!\n",
   1767                 filename);
   1768     GNUNET_break (0 == close (fd));
   1769     return GNUNET_OK;
   1770   }
   1771   if (0 != (sbuf.st_mode & (S_IWUSR | S_IRWXG | S_IRWXO)))
   1772   {
   1773     /* permission are NOT tight, try to patch them up! */
   1774     if (0 !=
   1775         fchmod (fd,
   1776                 S_IRUSR))
   1777     {
   1778       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1779                                 "fchmod",
   1780                                 filename);
   1781       /* refuse to use key if file has wrong permissions */
   1782       GNUNET_break (0 == close (fd));
   1783       return GNUNET_OK;
   1784     }
   1785   }
   1786   fh = GNUNET_DISK_get_handle_from_int_fd (fd);
   1787   if (NULL == fh)
   1788   {
   1789     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1790                               "open",
   1791                               filename);
   1792     GNUNET_break (0 == close (fd));
   1793     return GNUNET_OK;
   1794   }
   1795   if (sbuf.st_size > 16 * 1024)
   1796   {
   1797     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1798                 "File `%s' too big to be a private key\n",
   1799                 filename);
   1800     GNUNET_DISK_file_close (fh);
   1801     return GNUNET_OK;
   1802   }
   1803   ptr = GNUNET_DISK_file_map (fh,
   1804                               &map,
   1805                               GNUNET_DISK_MAP_TYPE_READ,
   1806                               (size_t) sbuf.st_size);
   1807   if (NULL == ptr)
   1808   {
   1809     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
   1810                               "mmap",
   1811                               filename);
   1812     GNUNET_DISK_file_close (fh);
   1813     return GNUNET_OK;
   1814   }
   1815   parse_key (denom,
   1816              filename,
   1817              ptr,
   1818              (size_t) sbuf.st_size);
   1819   GNUNET_DISK_file_unmap (map);
   1820   GNUNET_DISK_file_close (fh);
   1821   return GNUNET_OK;
   1822 }
   1823 
   1824 
   1825 /**
   1826  * Parse configuration for denomination type parameters.  Also determines
   1827  * our anchor by looking at the existing denominations of the same type.
   1828  *
   1829  * @param cfg configuration to use
   1830  * @param ct section in the configuration file giving the denomination type parameters
   1831  * @param[out] denom set to the denomination parameters from the configuration
   1832  * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid
   1833  */
   1834 static enum GNUNET_GenericReturnValue
   1835 parse_denomination_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg,
   1836                         const char *ct,
   1837                         struct Denomination *denom)
   1838 {
   1839   unsigned long long rsa_keysize;
   1840   char *secname;
   1841 
   1842   GNUNET_asprintf (&secname,
   1843                    "%s-secmod-rsa",
   1844                    globals->section);
   1845   if (GNUNET_OK !=
   1846       GNUNET_CONFIGURATION_get_value_time (cfg,
   1847                                            ct,
   1848                                            "DURATION_WITHDRAW",
   1849                                            &denom->duration_withdraw))
   1850   {
   1851     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1852                                ct,
   1853                                "DURATION_WITHDRAW");
   1854     GNUNET_free (secname);
   1855     return GNUNET_SYSERR;
   1856   }
   1857   if (GNUNET_TIME_relative_cmp (denom->duration_withdraw,
   1858                                 <,
   1859                                 GNUNET_TIME_UNIT_SECONDS))
   1860   {
   1861     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   1862                                ct,
   1863                                "DURATION_WITHDRAW",
   1864                                "less than one second is not supported");
   1865     GNUNET_free (secname);
   1866     return GNUNET_SYSERR;
   1867   }
   1868   if (GNUNET_TIME_relative_cmp (overlap_duration,
   1869                                 >=,
   1870                                 denom->duration_withdraw))
   1871   {
   1872     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   1873                                secname,
   1874                                "OVERLAP_DURATION",
   1875                                "Value given must be smaller than value for DURATION_WITHDRAW!");
   1876     GNUNET_free (secname);
   1877     return GNUNET_SYSERR;
   1878   }
   1879   if (GNUNET_OK !=
   1880       GNUNET_CONFIGURATION_get_value_number (cfg,
   1881                                              ct,
   1882                                              "RSA_KEYSIZE",
   1883                                              &rsa_keysize))
   1884   {
   1885     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1886                                ct,
   1887                                "RSA_KEYSIZE");
   1888     GNUNET_free (secname);
   1889     return GNUNET_SYSERR;
   1890   }
   1891   if ( (rsa_keysize > 4 * 2048) ||
   1892        (rsa_keysize < 1024) )
   1893   {
   1894     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
   1895                                ct,
   1896                                "RSA_KEYSIZE",
   1897                                "Given RSA keysize outside of permitted range [1024,8192]\n");
   1898     GNUNET_free (secname);
   1899     return GNUNET_SYSERR;
   1900   }
   1901   GNUNET_free (secname);
   1902   denom->rsa_keysize = (unsigned int) rsa_keysize;
   1903   denom->section = GNUNET_strdup (ct);
   1904   return GNUNET_OK;
   1905 }
   1906 
   1907 
   1908 /**
   1909  * Closure for #load_denominations.
   1910  */
   1911 struct LoadContext
   1912 {
   1913 
   1914   /**
   1915    * Configuration to use.
   1916    */
   1917   const struct GNUNET_CONFIGURATION_Handle *cfg;
   1918 
   1919   /**
   1920    * Configuration section prefix to use for denomination settings.
   1921    * "coin_" for the exchange, "doco_" for Donau.
   1922    */
   1923   const char *cprefix;
   1924 
   1925   /**
   1926    * Status, to be set to #GNUNET_SYSERR on failure
   1927    */
   1928   enum GNUNET_GenericReturnValue ret;
   1929 };
   1930 
   1931 
   1932 /**
   1933  * Generate new denomination signing keys for the denomination type of the given @a
   1934  * denomination_alias.
   1935  *
   1936  * @param cls a `struct LoadContext`, with 'ret' to be set to #GNUNET_SYSERR on failure
   1937  * @param denomination_alias name of the denomination's section in the configuration
   1938  */
   1939 static void
   1940 load_denominations (void *cls,
   1941                     const char *denomination_alias)
   1942 {
   1943   struct LoadContext *ctx = cls;
   1944   struct Denomination *denom;
   1945   char *cipher;
   1946 
   1947   if (0 != strncasecmp (denomination_alias,
   1948                         ctx->cprefix,
   1949                         strlen (ctx->cprefix)))
   1950     return; /* not a denomination type definition */
   1951   if (GNUNET_OK !=
   1952       GNUNET_CONFIGURATION_get_value_string (ctx->cfg,
   1953                                              denomination_alias,
   1954                                              "CIPHER",
   1955                                              &cipher))
   1956   {
   1957     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   1958                                denomination_alias,
   1959                                "CIPHER");
   1960     return;
   1961   }
   1962   if (0 != strcmp (cipher,
   1963                    "RSA"))
   1964   {
   1965     GNUNET_free (cipher);
   1966     return; /* Ignore denominations of other types than CS */
   1967   }
   1968   GNUNET_free (cipher);
   1969   denom = GNUNET_new (struct Denomination);
   1970   if (GNUNET_OK !=
   1971       parse_denomination_cfg (ctx->cfg,
   1972                               denomination_alias,
   1973                               denom))
   1974   {
   1975     ctx->ret = GNUNET_SYSERR;
   1976     GNUNET_free (denom);
   1977     return;
   1978   }
   1979   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
   1980               "Loading keys for denomination %s\n",
   1981               denom->section);
   1982   {
   1983     char *dname;
   1984 
   1985     GNUNET_asprintf (&dname,
   1986                      "%s/%s",
   1987                      keydir,
   1988                      denom->section);
   1989     GNUNET_break (GNUNET_OK ==
   1990                   GNUNET_DISK_directory_create (dname));
   1991     GNUNET_DISK_directory_scan (dname,
   1992                                 &import_key,
   1993                                 denom);
   1994     GNUNET_free (dname);
   1995   }
   1996   GNUNET_CONTAINER_DLL_insert (denom_head,
   1997                                denom_tail,
   1998                                denom);
   1999 }
   2000 
   2001 
   2002 /**
   2003  * Load the various duration values from @a cfg
   2004  *
   2005  * @param cfg configuration to use
   2006  * @return #GNUNET_OK on success
   2007  */
   2008 static enum GNUNET_GenericReturnValue
   2009 load_durations (const struct GNUNET_CONFIGURATION_Handle *cfg)
   2010 {
   2011   char *secname;
   2012 
   2013   GNUNET_asprintf (&secname,
   2014                    "%s-secmod-rsa",
   2015                    globals->section);
   2016   if (GNUNET_OK !=
   2017       GNUNET_CONFIGURATION_get_value_time (cfg,
   2018                                            secname,
   2019                                            "OVERLAP_DURATION",
   2020                                            &overlap_duration))
   2021   {
   2022     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2023                                secname,
   2024                                "OVERLAP_DURATION");
   2025     GNUNET_free (secname);
   2026     return GNUNET_SYSERR;
   2027   }
   2028   if (GNUNET_OK !=
   2029       GNUNET_CONFIGURATION_get_value_time (cfg,
   2030                                            secname,
   2031                                            "LOOKAHEAD_SIGN",
   2032                                            &lookahead_sign))
   2033   {
   2034     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2035                                secname,
   2036                                "LOOKAHEAD_SIGN");
   2037     GNUNET_free (secname);
   2038     return GNUNET_SYSERR;
   2039   }
   2040   GNUNET_free (secname);
   2041   return GNUNET_OK;
   2042 }
   2043 
   2044 
   2045 /**
   2046  * Function run on shutdown. Stops the various jobs (nicely).
   2047  *
   2048  * @param cls NULL
   2049  */
   2050 static void
   2051 do_shutdown (void *cls)
   2052 {
   2053   (void) cls;
   2054   TES_listen_stop ();
   2055   if (NULL != keygen_task)
   2056   {
   2057     GNUNET_SCHEDULER_cancel (keygen_task);
   2058     keygen_task = NULL;
   2059   }
   2060   stop_workers ();
   2061   sem_done (&worker_sem);
   2062 }
   2063 
   2064 
   2065 void
   2066 TALER_SECMOD_rsa_run (void *cls,
   2067                       char *const *args,
   2068                       const char *cfgfile,
   2069                       const struct GNUNET_CONFIGURATION_Handle *cfg)
   2070 {
   2071   static struct TES_Callbacks cb = {
   2072     .dispatch = rsa_work_dispatch,
   2073     .updater = rsa_update_client_keys,
   2074     .init = rsa_client_init
   2075   };
   2076   struct TALER_SECMOD_Options *opt = cls;
   2077   char *secname;
   2078 
   2079   (void) args;
   2080   (void) cfgfile;
   2081   globals = opt;
   2082   if (GNUNET_TIME_timestamp_cmp (opt->global_now,
   2083                                  !=,
   2084                                  opt->global_now_tmp))
   2085   {
   2086     /* The user gave "--now", use it! */
   2087     opt->global_now = opt->global_now_tmp;
   2088   }
   2089   else
   2090   {
   2091     /* get current time again, we may be timetraveling! */
   2092     opt->global_now = GNUNET_TIME_timestamp_get ();
   2093   }
   2094   GNUNET_asprintf (&secname,
   2095                    "%s-secmod-rsa",
   2096                    opt->section);
   2097   if (GNUNET_OK !=
   2098       GNUNET_CONFIGURATION_get_value_filename (cfg,
   2099                                                secname,
   2100                                                "KEY_DIR",
   2101                                                &keydir))
   2102   {
   2103     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
   2104                                secname,
   2105                                "KEY_DIR");
   2106     GNUNET_free (secname);
   2107     opt->global_ret = EXIT_NOTCONFIGURED;
   2108     return;
   2109   }
   2110   if (GNUNET_OK !=
   2111       load_durations (cfg))
   2112   {
   2113     opt->global_ret = EXIT_NOTCONFIGURED;
   2114     GNUNET_free (secname);
   2115     return;
   2116   }
   2117   opt->global_ret = TES_listen_start (cfg,
   2118                                       secname,
   2119                                       &cb);
   2120   GNUNET_free (secname);
   2121   if (0 != opt->global_ret)
   2122     return;
   2123   sem_init (&worker_sem,
   2124             0);
   2125   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
   2126                                  NULL);
   2127   if (0 == opt->max_workers)
   2128   {
   2129     long lret;
   2130 
   2131     lret = sysconf (_SC_NPROCESSORS_CONF);
   2132     if (lret <= 0)
   2133       lret = 1;
   2134     opt->max_workers = (unsigned int) lret;
   2135   }
   2136 
   2137   for (unsigned int i = 0; i<opt->max_workers; i++)
   2138     if (GNUNET_OK !=
   2139         start_worker ())
   2140     {
   2141       GNUNET_SCHEDULER_shutdown ();
   2142       return;
   2143     }
   2144   /* Load denominations */
   2145   keys = GNUNET_CONTAINER_multihashmap_create (65536,
   2146                                                true);
   2147   {
   2148     struct LoadContext lc = {
   2149       .cfg = cfg,
   2150       .ret = GNUNET_OK,
   2151       .cprefix = opt->cprefix
   2152     };
   2153     bool wake = true;
   2154 
   2155     GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
   2156     GNUNET_CONFIGURATION_iterate_sections (cfg,
   2157                                            &load_denominations,
   2158                                            &lc);
   2159     GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
   2160     if (GNUNET_OK != lc.ret)
   2161     {
   2162       opt->global_ret = EXIT_FAILURE;
   2163       GNUNET_SCHEDULER_shutdown ();
   2164       return;
   2165     }
   2166     create_missing_keys (opt,
   2167                          &wake);
   2168   }
   2169   if (NULL == denom_head)
   2170   {
   2171     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   2172                 "No RSA denominations configured. Make sure section names start with `%s' if you are using RSA!\n",
   2173                 opt->cprefix);
   2174     TES_wake_clients ();
   2175     return;
   2176   }
   2177   /* start job to keep keys up-to-date; MUST be run before the #listen_task,
   2178      hence with priority. */
   2179   keygen_task = GNUNET_SCHEDULER_add_with_priority (
   2180     GNUNET_SCHEDULER_PRIORITY_URGENT,
   2181     &update_denominations,
   2182     opt);
   2183 }