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


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