LCOV - code coverage report
Current view: top level - util - secmod_rsa.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 68.9 % 687 473
Test Date: 2026-01-04 22:17:00 Functions: 93.8 % 32 30

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

Generated by: LCOV version 2.0-1