LCOV - code coverage report
Current view: top level - util - secmod_rsa.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 524 687 76.3 %
Date: 2025-06-05 21:03:14 Functions: 32 32 100.0 %

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

Generated by: LCOV version 1.16