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


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