exchange

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

crypto_helper_cs.c (38996B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2020, 2021, 2022 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/crypto_helper_cs.c
     18  * @brief utility functions for running out-of-process private key operations
     19  * @author Christian Grothoff
     20  */
     21 #include "taler/platform.h"
     22 #include "taler/taler_util.h"
     23 #include "taler/taler_signatures.h"
     24 #include "secmod_cs.h"
     25 #include <poll.h>
     26 #include "crypto_helper_common.h"
     27 
     28 
     29 struct TALER_CRYPTO_CsDenominationHelper
     30 {
     31   /**
     32    * Function to call with updates to available key material.
     33    */
     34   TALER_CRYPTO_CsDenominationKeyStatusCallback dkc;
     35 
     36   /**
     37    * Closure for @e dkc
     38    */
     39   void *dkc_cls;
     40 
     41   /**
     42    * Socket address of the denomination helper process.
     43    * Used to reconnect if the connection breaks.
     44    */
     45   struct sockaddr_un sa;
     46 
     47   /**
     48    * The UNIX domain socket, -1 if we are currently not connected.
     49    */
     50   int sock;
     51 
     52   /**
     53    * Have we ever been sync'ed?
     54    */
     55   bool synced;
     56 };
     57 
     58 
     59 /**
     60  * Disconnect from the helper process.  Updates
     61  * @e sock field in @a dh.
     62  *
     63  * @param[in,out] dh handle to tear down connection of
     64  */
     65 static void
     66 do_disconnect (struct TALER_CRYPTO_CsDenominationHelper *dh)
     67 {
     68   GNUNET_break (0 == close (dh->sock));
     69   dh->sock = -1;
     70   dh->synced = false;
     71 }
     72 
     73 
     74 /**
     75  * Try to connect to the helper process.  Updates
     76  * @e sock field in @a dh.
     77  *
     78  * @param[in,out] dh handle to establish connection for
     79  * @return #GNUNET_OK on success
     80  */
     81 static enum GNUNET_GenericReturnValue
     82 try_connect (struct TALER_CRYPTO_CsDenominationHelper *dh)
     83 {
     84   if (-1 != dh->sock)
     85     return GNUNET_OK;
     86   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     87               "Establishing connection!\n");
     88   dh->sock = socket (AF_UNIX,
     89                      SOCK_STREAM,
     90                      0);
     91   if (-1 == dh->sock)
     92   {
     93     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     94                          "socket");
     95     return GNUNET_SYSERR;
     96   }
     97   if (0 !=
     98       connect (dh->sock,
     99                (const struct sockaddr *) &dh->sa,
    100                sizeof (dh->sa)))
    101   {
    102     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    103                               "connect",
    104                               dh->sa.sun_path);
    105     do_disconnect (dh);
    106     return GNUNET_SYSERR;
    107   }
    108   TALER_CRYPTO_helper_cs_poll (dh);
    109   return GNUNET_OK;
    110 }
    111 
    112 
    113 struct TALER_CRYPTO_CsDenominationHelper *
    114 TALER_CRYPTO_helper_cs_connect (
    115   const struct GNUNET_CONFIGURATION_Handle *cfg,
    116   const char *section,
    117   TALER_CRYPTO_CsDenominationKeyStatusCallback dkc,
    118   void *dkc_cls)
    119 {
    120   struct TALER_CRYPTO_CsDenominationHelper *dh;
    121   char *unixpath;
    122   char *secname;
    123 
    124   GNUNET_asprintf (&secname,
    125                    "%s-secmod-cs",
    126                    section);
    127   if (GNUNET_OK !=
    128       GNUNET_CONFIGURATION_get_value_filename (cfg,
    129                                                secname,
    130                                                "UNIXPATH",
    131                                                &unixpath))
    132   {
    133     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    134                                secname,
    135                                "UNIXPATH");
    136     GNUNET_free (secname);
    137     return NULL;
    138   }
    139   /* we use >= here because we want the sun_path to always
    140      be 0-terminated */
    141   if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
    142   {
    143     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
    144                                secname,
    145                                "UNIXPATH",
    146                                "path too long");
    147     GNUNET_free (unixpath);
    148     GNUNET_free (secname);
    149     return NULL;
    150   }
    151   GNUNET_free (secname);
    152   dh = GNUNET_new (struct TALER_CRYPTO_CsDenominationHelper);
    153   dh->dkc = dkc;
    154   dh->dkc_cls = dkc_cls;
    155   dh->sa.sun_family = AF_UNIX;
    156   strncpy (dh->sa.sun_path,
    157            unixpath,
    158            sizeof (dh->sa.sun_path) - 1);
    159   GNUNET_free (unixpath);
    160   dh->sock = -1;
    161   if (GNUNET_OK !=
    162       try_connect (dh))
    163   {
    164     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    165                 "Could not connect to %s. Will keep trying\n",
    166                 "taler-exchange-helper-secmod-cs");
    167   }
    168   return dh;
    169 }
    170 
    171 
    172 /**
    173  * Handle a #TALER_HELPER_CS_MT_AVAIL message from the helper.
    174  *
    175  * @param dh helper context
    176  * @param hdr message that we received
    177  * @return #GNUNET_OK on success
    178  */
    179 static enum GNUNET_GenericReturnValue
    180 handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
    181                  const struct GNUNET_MessageHeader *hdr)
    182 {
    183   const struct TALER_CRYPTO_CsKeyAvailableNotification *kan
    184     = (const struct TALER_CRYPTO_CsKeyAvailableNotification *) hdr;
    185   const char *buf = (const char *) &kan[1];
    186   const char *section_name;
    187   uint16_t snl;
    188 
    189   if (sizeof (*kan) > ntohs (hdr->size))
    190   {
    191     GNUNET_break_op (0);
    192     return GNUNET_SYSERR;
    193   }
    194   snl = ntohs (kan->section_name_len);
    195   if (ntohs (hdr->size) != sizeof (*kan) + snl)
    196   {
    197     GNUNET_break_op (0);
    198     return GNUNET_SYSERR;
    199   }
    200   if (0 == snl)
    201   {
    202     GNUNET_break_op (0);
    203     return GNUNET_SYSERR;
    204   }
    205   section_name = buf;
    206   if ('\0' != section_name[snl - 1])
    207   {
    208     GNUNET_break_op (0);
    209     return GNUNET_SYSERR;
    210   }
    211 
    212   {
    213     struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
    214     struct TALER_CsPubHashP h_cs;
    215 
    216     bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
    217     bsign_pub->cipher = GNUNET_CRYPTO_BSA_CS;
    218     bsign_pub->rc = 1;
    219     bsign_pub->details.cs_public_key = kan->denom_pub;
    220 
    221     GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
    222                         sizeof (bsign_pub->details.cs_public_key),
    223                         &bsign_pub->pub_key_hash);
    224     h_cs.hash = bsign_pub->pub_key_hash;
    225     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    226                 "Received CS key %s (%s)\n",
    227                 GNUNET_h2s (&h_cs.hash),
    228                 section_name);
    229     if (GNUNET_OK !=
    230         TALER_exchange_secmod_cs_verify (
    231           &h_cs,
    232           section_name,
    233           GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
    234           GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
    235           &kan->secm_pub,
    236           &kan->secm_sig))
    237     {
    238       GNUNET_break_op (0);
    239       GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
    240       return GNUNET_SYSERR;
    241     }
    242     dh->dkc (dh->dkc_cls,
    243              section_name,
    244              GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
    245              GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
    246              &h_cs,
    247              bsign_pub,
    248              &kan->secm_pub,
    249              &kan->secm_sig);
    250     GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
    251   }
    252   return GNUNET_OK;
    253 }
    254 
    255 
    256 /**
    257  * Handle a #TALER_HELPER_CS_MT_PURGE message from the helper.
    258  *
    259  * @param dh helper context
    260  * @param hdr message that we received
    261  * @return #GNUNET_OK on success
    262  */
    263 static enum GNUNET_GenericReturnValue
    264 handle_mt_purge (struct TALER_CRYPTO_CsDenominationHelper *dh,
    265                  const struct GNUNET_MessageHeader *hdr)
    266 {
    267   const struct TALER_CRYPTO_CsKeyPurgeNotification *pn
    268     = (const struct TALER_CRYPTO_CsKeyPurgeNotification *) hdr;
    269 
    270   if (sizeof (*pn) != ntohs (hdr->size))
    271   {
    272     GNUNET_break_op (0);
    273     return GNUNET_SYSERR;
    274   }
    275   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    276               "Received revocation of denomination key %s\n",
    277               GNUNET_h2s (&pn->h_cs.hash));
    278   dh->dkc (dh->dkc_cls,
    279            NULL,
    280            GNUNET_TIME_UNIT_ZERO_TS,
    281            GNUNET_TIME_UNIT_ZERO,
    282            &pn->h_cs,
    283            NULL,
    284            NULL,
    285            NULL);
    286   return GNUNET_OK;
    287 }
    288 
    289 
    290 void
    291 TALER_CRYPTO_helper_cs_poll (struct TALER_CRYPTO_CsDenominationHelper *dh)
    292 {
    293   char buf[UINT16_MAX];
    294   size_t off = 0;
    295   unsigned int retry_limit = 3;
    296   const struct GNUNET_MessageHeader *hdr
    297     = (const struct GNUNET_MessageHeader *) buf;
    298 
    299   if (GNUNET_OK !=
    300       try_connect (dh))
    301     return; /* give up */
    302   while (1)
    303   {
    304     uint16_t msize;
    305     ssize_t ret;
    306 
    307     ret = recv (dh->sock,
    308                 buf + off,
    309                 sizeof (buf) - off,
    310                 (dh->synced && (0 == off))
    311                 ? MSG_DONTWAIT
    312                 : 0);
    313     if (ret < 0)
    314     {
    315       if (EINTR == errno)
    316         continue;
    317       if (EAGAIN == errno)
    318       {
    319         GNUNET_assert (dh->synced);
    320         GNUNET_assert (0 == off);
    321         break;
    322       }
    323       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    324                            "recv");
    325       do_disconnect (dh);
    326       if (0 == retry_limit)
    327         return; /* give up */
    328       if (GNUNET_OK !=
    329           try_connect (dh))
    330         return; /* give up */
    331       retry_limit--;
    332       continue;
    333     }
    334     if (0 == ret)
    335     {
    336       GNUNET_break (0 == off);
    337       return;
    338     }
    339     off += ret;
    340 more:
    341     if (off < sizeof (struct GNUNET_MessageHeader))
    342       continue;
    343     msize = ntohs (hdr->size);
    344     if (off < msize)
    345       continue;
    346     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    347                 "Received message of type %u and length %u\n",
    348                 (unsigned int) ntohs (hdr->type),
    349                 (unsigned int) msize);
    350     switch (ntohs (hdr->type))
    351     {
    352     case TALER_HELPER_CS_MT_AVAIL:
    353       if (GNUNET_OK !=
    354           handle_mt_avail (dh,
    355                            hdr))
    356       {
    357         GNUNET_break_op (0);
    358         do_disconnect (dh);
    359         return;
    360       }
    361       break;
    362     case TALER_HELPER_CS_MT_PURGE:
    363       if (GNUNET_OK !=
    364           handle_mt_purge (dh,
    365                            hdr))
    366       {
    367         GNUNET_break_op (0);
    368         do_disconnect (dh);
    369         return;
    370       }
    371       break;
    372     case TALER_HELPER_CS_SYNCED:
    373       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    374                   "Now synchronized with CS helper\n");
    375       dh->synced = true;
    376       break;
    377     default:
    378       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    379                   "Received unexpected message of type %d (len: %u)\n",
    380                   (unsigned int) ntohs (hdr->type),
    381                   (unsigned int) msize);
    382       GNUNET_break_op (0);
    383       do_disconnect (dh);
    384       return;
    385     }
    386     memmove (buf,
    387              &buf[msize],
    388              off - msize);
    389     off -= msize;
    390     goto more;
    391   }
    392 }
    393 
    394 
    395 enum TALER_ErrorCode
    396 TALER_CRYPTO_helper_cs_sign (
    397   struct TALER_CRYPTO_CsDenominationHelper *dh,
    398   const struct TALER_CRYPTO_CsSignRequest *req,
    399   bool for_melt,
    400   struct TALER_BlindedDenominationSignature *bs)
    401 {
    402   enum TALER_ErrorCode ec = TALER_EC_INVALID;
    403   const struct TALER_CsPubHashP *h_cs = req->h_cs;
    404 
    405   memset (bs,
    406           0,
    407           sizeof (*bs));
    408   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    409               "Starting signature process\n");
    410   if (GNUNET_OK !=
    411       try_connect (dh))
    412   {
    413     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    414                 "Failed to connect to helper\n");
    415     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    416   }
    417 
    418   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    419               "Requesting signature\n");
    420   {
    421     char buf[sizeof (struct TALER_CRYPTO_CsSignRequestMessage)];
    422     struct TALER_CRYPTO_CsSignRequestMessage *sr
    423       = (struct TALER_CRYPTO_CsSignRequestMessage *) buf;
    424 
    425     sr->header.size = htons (sizeof (buf));
    426     sr->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
    427     sr->for_melt = htonl (for_melt ? 1 : 0);
    428     sr->h_cs = *h_cs;
    429     sr->message = *req->blinded_planchet;
    430     if (GNUNET_OK !=
    431         TALER_crypto_helper_send_all (dh->sock,
    432                                       buf,
    433                                       sizeof (buf)))
    434     {
    435       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    436                            "send");
    437       do_disconnect (dh);
    438       return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    439     }
    440   }
    441 
    442   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    443               "Awaiting reply\n");
    444   {
    445     char buf[UINT16_MAX];
    446     size_t off = 0;
    447     const struct GNUNET_MessageHeader *hdr
    448       = (const struct GNUNET_MessageHeader *) buf;
    449     bool finished = false;
    450 
    451     while (1)
    452     {
    453       uint16_t msize;
    454       ssize_t ret;
    455 
    456       ret = recv (dh->sock,
    457                   &buf[off],
    458                   sizeof (buf) - off,
    459                   (finished && (0 == off))
    460                   ? MSG_DONTWAIT
    461                   : 0);
    462       if (ret < 0)
    463       {
    464         if (EINTR == errno)
    465           continue;
    466         if (EAGAIN == errno)
    467         {
    468           GNUNET_assert (finished);
    469           GNUNET_assert (0 == off);
    470           return ec;
    471         }
    472         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    473                              "recv");
    474         do_disconnect (dh);
    475         ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    476         break;
    477       }
    478       if (0 == ret)
    479       {
    480         GNUNET_break (0 == off);
    481         if (! finished)
    482           ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
    483         return ec;
    484       }
    485       off += ret;
    486 more:
    487       if (off < sizeof (struct GNUNET_MessageHeader))
    488         continue;
    489       msize = ntohs (hdr->size);
    490       if (off < msize)
    491         continue;
    492       switch (ntohs (hdr->type))
    493       {
    494       case TALER_HELPER_CS_MT_RES_SIGNATURE:
    495         if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
    496         {
    497           GNUNET_break_op (0);
    498           do_disconnect (dh);
    499           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    500           goto end;
    501         }
    502         if (finished)
    503         {
    504           GNUNET_break_op (0);
    505           do_disconnect (dh);
    506           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    507           goto end;
    508         }
    509         {
    510           const struct TALER_CRYPTO_SignResponse *sr =
    511             (const struct TALER_CRYPTO_SignResponse *) buf;
    512           struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
    513 
    514           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    515                       "Received signature\n");
    516           ec = TALER_EC_NONE;
    517           finished = true;
    518           blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
    519           blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
    520           blinded_sig->rc = 1;
    521           blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
    522           blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
    523           bs->blinded_sig = blinded_sig;
    524           break;
    525         }
    526       case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
    527         if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
    528         {
    529           GNUNET_break_op (0);
    530           do_disconnect (dh);
    531           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    532           goto end;
    533         }
    534         {
    535           const struct TALER_CRYPTO_SignFailure *sf =
    536             (const struct TALER_CRYPTO_SignFailure *) buf;
    537 
    538           ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
    539           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    540                       "Signing failed with status %d!\n",
    541                       ec);
    542           finished = true;
    543           break;
    544         }
    545       case TALER_HELPER_CS_MT_AVAIL:
    546         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    547                     "Received new key!\n");
    548         if (GNUNET_OK !=
    549             handle_mt_avail (dh,
    550                              hdr))
    551         {
    552           GNUNET_break_op (0);
    553           do_disconnect (dh);
    554           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    555           goto end;
    556         }
    557         break; /* while(1) loop ensures we recvfrom() again */
    558       case TALER_HELPER_CS_MT_PURGE:
    559         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    560                     "Received revocation!\n");
    561         if (GNUNET_OK !=
    562             handle_mt_purge (dh,
    563                              hdr))
    564         {
    565           GNUNET_break_op (0);
    566           do_disconnect (dh);
    567           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    568           goto end;
    569         }
    570         break; /* while(1) loop ensures we recvfrom() again */
    571       case TALER_HELPER_CS_SYNCED:
    572         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    573                     "Synchronized add odd time with CS helper!\n");
    574         dh->synced = true;
    575         break;
    576       default:
    577         GNUNET_break_op (0);
    578         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    579                     "Received unexpected message of type %u\n",
    580                     ntohs (hdr->type));
    581         do_disconnect (dh);
    582         ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    583         goto end;
    584       }
    585       memmove (buf,
    586                &buf[msize],
    587                off - msize);
    588       off -= msize;
    589       goto more;
    590     } /* while(1) */
    591 end:
    592     if (finished)
    593       TALER_blinded_denom_sig_free (bs);
    594     return ec;
    595   }
    596 }
    597 
    598 
    599 void
    600 TALER_CRYPTO_helper_cs_revoke (
    601   struct TALER_CRYPTO_CsDenominationHelper *dh,
    602   const struct TALER_CsPubHashP *h_cs)
    603 {
    604   struct TALER_CRYPTO_CsRevokeRequest rr = {
    605     .header.size = htons (sizeof (rr)),
    606     .header.type = htons (TALER_HELPER_CS_MT_REQ_REVOKE),
    607     .h_cs = *h_cs
    608   };
    609 
    610   if (GNUNET_OK !=
    611       try_connect (dh))
    612     return; /* give up */
    613   if (GNUNET_OK !=
    614       TALER_crypto_helper_send_all (dh->sock,
    615                                     &rr,
    616                                     sizeof (rr)))
    617   {
    618     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    619                          "send");
    620     do_disconnect (dh);
    621     return;
    622   }
    623   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    624               "Requested revocation of denomination key %s\n",
    625               GNUNET_h2s (&h_cs->hash));
    626 }
    627 
    628 
    629 enum TALER_ErrorCode
    630 TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
    631                                  const struct TALER_CRYPTO_CsDeriveRequest *cdr,
    632                                  bool for_melt,
    633                                  struct GNUNET_CRYPTO_CSPublicRPairP *crp)
    634 {
    635   enum TALER_ErrorCode ec = TALER_EC_INVALID;
    636   const struct TALER_CsPubHashP *h_cs = cdr->h_cs;
    637   const struct GNUNET_CRYPTO_CsSessionNonce *nonce = cdr->nonce;
    638 
    639   memset (crp,
    640           0,
    641           sizeof (*crp));
    642   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    643               "Starting R derivation process\n");
    644   if (GNUNET_OK !=
    645       try_connect (dh))
    646   {
    647     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    648                 "Failed to connect to helper\n");
    649     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    650   }
    651 
    652   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    653               "Requesting R\n");
    654   {
    655     struct TALER_CRYPTO_CsRDeriveRequest rdr = {
    656       .header.size = htons (sizeof (rdr)),
    657       .header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE),
    658       .for_melt = htonl (for_melt ? 1 : 0),
    659       .h_cs = *h_cs,
    660       .nonce = *nonce
    661     };
    662 
    663     if (GNUNET_OK !=
    664         TALER_crypto_helper_send_all (dh->sock,
    665                                       &rdr,
    666                                       sizeof (rdr)))
    667     {
    668       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    669                            "send");
    670       do_disconnect (dh);
    671       return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    672     }
    673   }
    674 
    675   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    676               "Awaiting reply\n");
    677   {
    678     char buf[UINT16_MAX];
    679     size_t off = 0;
    680     const struct GNUNET_MessageHeader *hdr
    681       = (const struct GNUNET_MessageHeader *) buf;
    682     bool finished = false;
    683 
    684     while (1)
    685     {
    686       uint16_t msize;
    687       ssize_t ret;
    688 
    689       ret = recv (dh->sock,
    690                   &buf[off],
    691                   sizeof (buf) - off,
    692                   (finished && (0 == off))
    693                   ? MSG_DONTWAIT
    694                   : 0);
    695       if (ret < 0)
    696       {
    697         if (EINTR == errno)
    698           continue;
    699         if (EAGAIN == errno)
    700         {
    701           GNUNET_assert (finished);
    702           GNUNET_assert (0 == off);
    703           return ec;
    704         }
    705         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    706                              "recv");
    707         do_disconnect (dh);
    708         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    709       }
    710       if (0 == ret)
    711       {
    712         GNUNET_break (0 == off);
    713         if (! finished)
    714           return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
    715         return ec;
    716       }
    717       off += ret;
    718 more:
    719       if (off < sizeof (struct GNUNET_MessageHeader))
    720         continue;
    721       msize = ntohs (hdr->size);
    722       if (off < msize)
    723         continue;
    724       switch (ntohs (hdr->type))
    725       {
    726       case TALER_HELPER_CS_MT_RES_RDERIVE:
    727         if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
    728         {
    729           GNUNET_break_op (0);
    730           do_disconnect (dh);
    731           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    732         }
    733         if (finished)
    734         {
    735           GNUNET_break_op (0);
    736           do_disconnect (dh);
    737           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    738         }
    739         {
    740           const struct TALER_CRYPTO_RDeriveResponse *rdr =
    741             (const struct TALER_CRYPTO_RDeriveResponse *) buf;
    742 
    743           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    744                       "Received R\n");
    745           finished = true;
    746           ec = TALER_EC_NONE;
    747           *crp = rdr->r_pub;
    748           break;
    749         }
    750       case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
    751         if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
    752         {
    753           GNUNET_break_op (0);
    754           do_disconnect (dh);
    755           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    756         }
    757         {
    758           const struct TALER_CRYPTO_RDeriveFailure *rdf =
    759             (const struct TALER_CRYPTO_RDeriveFailure *) buf;
    760 
    761           ec = (enum TALER_ErrorCode) (int) ntohl (rdf->ec);
    762           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    763                       "R derivation failed!\n");
    764           finished = true;
    765           break;
    766         }
    767       case TALER_HELPER_CS_MT_AVAIL:
    768         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    769                     "Received new key!\n");
    770         if (GNUNET_OK !=
    771             handle_mt_avail (dh,
    772                              hdr))
    773         {
    774           GNUNET_break_op (0);
    775           do_disconnect (dh);
    776           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    777         }
    778         break; /* while(1) loop ensures we recvfrom() again */
    779       case TALER_HELPER_CS_MT_PURGE:
    780         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    781                     "Received revocation!\n");
    782         if (GNUNET_OK !=
    783             handle_mt_purge (dh,
    784                              hdr))
    785         {
    786           GNUNET_break_op (0);
    787           do_disconnect (dh);
    788           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    789         }
    790         break; /* while(1) loop ensures we recvfrom() again */
    791       case TALER_HELPER_CS_SYNCED:
    792         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    793                     "Synchronized add odd time with CS helper!\n");
    794         dh->synced = true;
    795         break;
    796       default:
    797         GNUNET_break_op (0);
    798         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    799                     "Received unexpected message of type %u\n",
    800                     ntohs (hdr->type));
    801         do_disconnect (dh);
    802         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    803       }
    804       memmove (buf,
    805                &buf[msize],
    806                off - msize);
    807       off -= msize;
    808       goto more;
    809     } /* while(1) */
    810   }
    811 }
    812 
    813 
    814 enum TALER_ErrorCode
    815 TALER_CRYPTO_helper_cs_batch_sign (
    816   struct TALER_CRYPTO_CsDenominationHelper *dh,
    817   unsigned int reqs_length,
    818   const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
    819   bool for_melt,
    820   struct TALER_BlindedDenominationSignature bss[static reqs_length])
    821 {
    822   enum TALER_ErrorCode ec = TALER_EC_INVALID;
    823   unsigned int rpos;
    824   unsigned int rend;
    825   unsigned int wpos;
    826 
    827   memset (bss,
    828           0,
    829           sizeof (*bss) * reqs_length);
    830   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    831               "Starting signature process\n");
    832   if (GNUNET_OK !=
    833       try_connect (dh))
    834   {
    835     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    836                 "Failed to connect to helper\n");
    837     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    838   }
    839 
    840   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    841               "Requesting %u signatures\n",
    842               reqs_length);
    843   rpos = 0;
    844   rend = 0;
    845   wpos = 0;
    846   while (rpos < reqs_length)
    847   {
    848     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
    849 
    850     while ( (rend < reqs_length) &&
    851             (mlen + sizeof (struct TALER_CRYPTO_CsSignRequestMessage)
    852              < UINT16_MAX) )
    853     {
    854       mlen += sizeof (struct TALER_CRYPTO_CsSignRequestMessage);
    855       rend++;
    856     }
    857     {
    858       char obuf[mlen] GNUNET_ALIGN;
    859       struct TALER_CRYPTO_BatchSignRequest *bsr
    860         = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
    861       void *wbuf;
    862 
    863       bsr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_SIGN);
    864       bsr->header.size = htons (mlen);
    865       bsr->batch_size = htonl (rend - rpos);
    866       wbuf = &bsr[1];
    867       for (unsigned int i = rpos; i<rend; i++)
    868       {
    869         struct TALER_CRYPTO_CsSignRequestMessage *csm = wbuf;
    870         const struct TALER_CRYPTO_CsSignRequest *csr = &reqs[i];
    871 
    872         csm->header.size = htons (sizeof (*csm));
    873         csm->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
    874         csm->for_melt = htonl (for_melt ? 1 : 0);
    875         csm->h_cs = *csr->h_cs;
    876         csm->message = *csr->blinded_planchet;
    877         wbuf += sizeof (*csm);
    878       }
    879       GNUNET_assert (wbuf == &obuf[mlen]);
    880       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    881                   "Sending batch request [%u-%u)\n",
    882                   rpos,
    883                   rend);
    884       if (GNUNET_OK !=
    885           TALER_crypto_helper_send_all (dh->sock,
    886                                         obuf,
    887                                         sizeof (obuf)))
    888       {
    889         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    890                              "send");
    891         do_disconnect (dh);
    892         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    893       }
    894     } /* end of obuf scope */
    895     rpos = rend;
    896     {
    897       char buf[UINT16_MAX];
    898       size_t off = 0;
    899       const struct GNUNET_MessageHeader *hdr
    900         = (const struct GNUNET_MessageHeader *) buf;
    901       bool finished = false;
    902 
    903       while (1)
    904       {
    905         uint16_t msize;
    906         ssize_t ret;
    907 
    908         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    909                     "Awaiting reply at %u (up to %u)\n",
    910                     wpos,
    911                     rend);
    912         ret = recv (dh->sock,
    913                     &buf[off],
    914                     sizeof (buf) - off,
    915                     (finished && (0 == off))
    916                   ? MSG_DONTWAIT
    917                   : 0);
    918         if (ret < 0)
    919         {
    920           if (EINTR == errno)
    921             continue;
    922           if (EAGAIN == errno)
    923           {
    924             GNUNET_assert (finished);
    925             GNUNET_assert (0 == off);
    926             break;
    927           }
    928           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    929                                "recv");
    930           do_disconnect (dh);
    931           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    932         }
    933         if (0 == ret)
    934         {
    935           GNUNET_break (0 == off);
    936           if (! finished)
    937             return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
    938           if (TALER_EC_NONE == ec)
    939             break;
    940           return ec;
    941         }
    942         off += ret;
    943 more:
    944         if (off < sizeof (struct GNUNET_MessageHeader))
    945           continue;
    946         msize = ntohs (hdr->size);
    947         if (off < msize)
    948           continue;
    949         switch (ntohs (hdr->type))
    950         {
    951         case TALER_HELPER_CS_MT_RES_SIGNATURE:
    952           if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
    953           {
    954             GNUNET_break_op (0);
    955             do_disconnect (dh);
    956             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    957           }
    958           if (finished)
    959           {
    960             GNUNET_break_op (0);
    961             do_disconnect (dh);
    962             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    963           }
    964           {
    965             const struct TALER_CRYPTO_SignResponse *sr =
    966               (const struct TALER_CRYPTO_SignResponse *) buf;
    967             struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
    968             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    969                         "Received %u signature\n",
    970                         wpos);
    971             blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
    972             blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
    973             blinded_sig->rc = 1;
    974             blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
    975             blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
    976 
    977             bss[wpos].blinded_sig = blinded_sig;
    978             wpos++;
    979             if (wpos == rend)
    980             {
    981               if (TALER_EC_INVALID == ec)
    982                 ec = TALER_EC_NONE;
    983               finished = true;
    984             }
    985             break;
    986           }
    987 
    988         case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
    989           if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
    990           {
    991             GNUNET_break_op (0);
    992             do_disconnect (dh);
    993             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    994           }
    995           {
    996             const struct TALER_CRYPTO_SignFailure *sf =
    997               (const struct TALER_CRYPTO_SignFailure *) buf;
    998 
    999             ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
   1000             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1001                         "Signing %u failed with status %d!\n",
   1002                         wpos,
   1003                         ec);
   1004             wpos++;
   1005             if (wpos == rend)
   1006             {
   1007               finished = true;
   1008             }
   1009             break;
   1010           }
   1011         case TALER_HELPER_CS_MT_AVAIL:
   1012           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1013                       "Received new key!\n");
   1014           if (GNUNET_OK !=
   1015               handle_mt_avail (dh,
   1016                                hdr))
   1017           {
   1018             GNUNET_break_op (0);
   1019             do_disconnect (dh);
   1020             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1021           }
   1022           break; /* while(1) loop ensures we recvfrom() again */
   1023         case TALER_HELPER_CS_MT_PURGE:
   1024           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1025                       "Received revocation!\n");
   1026           if (GNUNET_OK !=
   1027               handle_mt_purge (dh,
   1028                                hdr))
   1029           {
   1030             GNUNET_break_op (0);
   1031             do_disconnect (dh);
   1032             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1033           }
   1034           break; /* while(1) loop ensures we recvfrom() again */
   1035         case TALER_HELPER_CS_SYNCED:
   1036           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1037                       "Synchronized add odd time with CS helper!\n");
   1038           dh->synced = true;
   1039           break;
   1040         default:
   1041           GNUNET_break_op (0);
   1042           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1043                       "Received unexpected message of type %u\n",
   1044                       ntohs (hdr->type));
   1045           do_disconnect (dh);
   1046           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1047         }
   1048         memmove (buf,
   1049                  &buf[msize],
   1050                  off - msize);
   1051         off -= msize;
   1052         goto more;
   1053       } /* while(1) */
   1054     } /* scope */
   1055   } /* while (rpos < cdrs_length) */
   1056   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1057               "Existing with %u signatures and status %d\n",
   1058               wpos,
   1059               ec);
   1060   return ec;
   1061 }
   1062 
   1063 
   1064 enum TALER_ErrorCode
   1065 TALER_CRYPTO_helper_cs_r_batch_derive (
   1066   struct TALER_CRYPTO_CsDenominationHelper *dh,
   1067   unsigned int cdrs_length,
   1068   const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
   1069   bool for_melt,
   1070   struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length])
   1071 {
   1072   enum TALER_ErrorCode ec = TALER_EC_INVALID;
   1073   unsigned int rpos;
   1074   unsigned int rend;
   1075   unsigned int wpos;
   1076 
   1077   memset (crps,
   1078           0,
   1079           sizeof (*crps) * cdrs_length);
   1080   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1081               "Starting R derivation process\n");
   1082   if (GNUNET_OK !=
   1083       try_connect (dh))
   1084   {
   1085     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1086                 "Failed to connect to helper\n");
   1087     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
   1088   }
   1089 
   1090   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1091               "Requesting %u R pairs\n",
   1092               cdrs_length);
   1093   rpos = 0;
   1094   rend = 0;
   1095   wpos = 0;
   1096   while (rpos < cdrs_length)
   1097   {
   1098     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchDeriveRequest);
   1099 
   1100     while ( (rend < cdrs_length) &&
   1101             (mlen + sizeof (struct TALER_CRYPTO_CsRDeriveRequest)
   1102              < UINT16_MAX) )
   1103     {
   1104       mlen += sizeof (struct TALER_CRYPTO_CsRDeriveRequest);
   1105       rend++;
   1106     }
   1107     {
   1108       char obuf[mlen] GNUNET_ALIGN;
   1109       struct TALER_CRYPTO_BatchDeriveRequest *bdr
   1110         = (struct TALER_CRYPTO_BatchDeriveRequest *) obuf;
   1111       void *wbuf;
   1112 
   1113       bdr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_RDERIVE);
   1114       bdr->header.size = htons (mlen);
   1115       bdr->batch_size = htonl (rend - rpos);
   1116       wbuf = &bdr[1];
   1117       for (unsigned int i = rpos; i<rend; i++)
   1118       {
   1119         struct TALER_CRYPTO_CsRDeriveRequest *rdr = wbuf;
   1120         const struct TALER_CRYPTO_CsDeriveRequest *cdr = &cdrs[i];
   1121 
   1122         rdr->header.size = htons (sizeof (*rdr));
   1123         rdr->header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
   1124         rdr->for_melt = htonl (for_melt ? 1 : 0);
   1125         rdr->h_cs = *cdr->h_cs;
   1126         rdr->nonce = *cdr->nonce;
   1127         wbuf += sizeof (*rdr);
   1128       }
   1129       GNUNET_assert (wbuf == &obuf[mlen]);
   1130       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1131                   "Sending batch request [%u-%u)\n",
   1132                   rpos,
   1133                   rend);
   1134       if (GNUNET_OK !=
   1135           TALER_crypto_helper_send_all (dh->sock,
   1136                                         obuf,
   1137                                         sizeof (obuf)))
   1138       {
   1139         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
   1140                              "send");
   1141         do_disconnect (dh);
   1142         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
   1143       }
   1144     } /* end of obuf scope */
   1145     rpos = rend;
   1146     {
   1147       char buf[UINT16_MAX];
   1148       size_t off = 0;
   1149       const struct GNUNET_MessageHeader *hdr
   1150         = (const struct GNUNET_MessageHeader *) buf;
   1151       bool finished = false;
   1152 
   1153       while (1)
   1154       {
   1155         uint16_t msize;
   1156         ssize_t ret;
   1157 
   1158         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1159                     "Awaiting reply at %u (up to %u)\n",
   1160                     wpos,
   1161                     rend);
   1162         ret = recv (dh->sock,
   1163                     &buf[off],
   1164                     sizeof (buf) - off,
   1165                     (finished && (0 == off))
   1166                   ? MSG_DONTWAIT
   1167                   : 0);
   1168         if (ret < 0)
   1169         {
   1170           if (EINTR == errno)
   1171             continue;
   1172           if (EAGAIN == errno)
   1173           {
   1174             GNUNET_assert (finished);
   1175             GNUNET_assert (0 == off);
   1176             break;
   1177           }
   1178           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
   1179                                "recv");
   1180           do_disconnect (dh);
   1181           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
   1182         }
   1183         if (0 == ret)
   1184         {
   1185           GNUNET_break (0 == off);
   1186           if (! finished)
   1187             return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
   1188           if (TALER_EC_NONE == ec)
   1189             break;
   1190           return ec;
   1191         }
   1192         off += ret;
   1193 more:
   1194         if (off < sizeof (struct GNUNET_MessageHeader))
   1195           continue;
   1196         msize = ntohs (hdr->size);
   1197         if (off < msize)
   1198           continue;
   1199         switch (ntohs (hdr->type))
   1200         {
   1201         case TALER_HELPER_CS_MT_RES_RDERIVE:
   1202           if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
   1203           {
   1204             GNUNET_break_op (0);
   1205             do_disconnect (dh);
   1206             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1207           }
   1208           if (finished)
   1209           {
   1210             GNUNET_break_op (0);
   1211             do_disconnect (dh);
   1212             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1213           }
   1214           {
   1215             const struct TALER_CRYPTO_RDeriveResponse *rdr =
   1216               (const struct TALER_CRYPTO_RDeriveResponse *) buf;
   1217 
   1218             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1219                         "Received %u R pair\n",
   1220                         wpos);
   1221             crps[wpos] = rdr->r_pub;
   1222             wpos++;
   1223             if (wpos == rend)
   1224             {
   1225               if (TALER_EC_INVALID == ec)
   1226                 ec = TALER_EC_NONE;
   1227               finished = true;
   1228             }
   1229             break;
   1230           }
   1231         case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
   1232           if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
   1233           {
   1234             GNUNET_break_op (0);
   1235             do_disconnect (dh);
   1236             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1237           }
   1238           {
   1239             const struct TALER_CRYPTO_RDeriveFailure *rdf =
   1240               (const struct TALER_CRYPTO_RDeriveFailure *) buf;
   1241 
   1242             ec = (enum TALER_ErrorCode) (int) ntohl (rdf->ec);
   1243             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1244                         "R derivation %u failed with status %d!\n",
   1245                         wpos,
   1246                         ec);
   1247             wpos++;
   1248             if (wpos == rend)
   1249             {
   1250               finished = true;
   1251             }
   1252             break;
   1253           }
   1254         case TALER_HELPER_CS_MT_AVAIL:
   1255           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1256                       "Received new key!\n");
   1257           if (GNUNET_OK !=
   1258               handle_mt_avail (dh,
   1259                                hdr))
   1260           {
   1261             GNUNET_break_op (0);
   1262             do_disconnect (dh);
   1263             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1264           }
   1265           break; /* while(1) loop ensures we recvfrom() again */
   1266         case TALER_HELPER_CS_MT_PURGE:
   1267           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1268                       "Received revocation!\n");
   1269           if (GNUNET_OK !=
   1270               handle_mt_purge (dh,
   1271                                hdr))
   1272           {
   1273             GNUNET_break_op (0);
   1274             do_disconnect (dh);
   1275             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1276           }
   1277           break; /* while(1) loop ensures we recvfrom() again */
   1278         case TALER_HELPER_CS_SYNCED:
   1279           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
   1280                       "Synchronized add odd time with CS helper!\n");
   1281           dh->synced = true;
   1282           break;
   1283         default:
   1284           GNUNET_break_op (0);
   1285           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
   1286                       "Received unexpected message of type %u\n",
   1287                       ntohs (hdr->type));
   1288           do_disconnect (dh);
   1289           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
   1290         }
   1291         memmove (buf,
   1292                  &buf[msize],
   1293                  off - msize);
   1294         off -= msize;
   1295         goto more;
   1296       } /* while(1) */
   1297     } /* scope */
   1298   } /* while (rpos < cdrs_length) */
   1299   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
   1300               "Existing with %u signatures and status %d\n",
   1301               wpos,
   1302               ec);
   1303   return ec;
   1304 }
   1305 
   1306 
   1307 void
   1308 TALER_CRYPTO_helper_cs_disconnect (
   1309   struct TALER_CRYPTO_CsDenominationHelper *dh)
   1310 {
   1311   if (-1 != dh->sock)
   1312     do_disconnect (dh);
   1313   GNUNET_free (dh);
   1314 }
   1315 
   1316 
   1317 /* end of crypto_helper_cs.c */