LCOV - code coverage report
Current view: top level - util - taler-exchange-secmod-rsa.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 428 644 66.5 %
Date: 2021-08-30 06:43:37 Functions: 22 24 91.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14