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


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