exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

secmod_cs.c (69874B)


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