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


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