LCOV - code coverage report
Current view: top level - util - crypto_helper_cs.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 66.5 % 451 300
Test Date: 2026-05-12 15:34:29 Functions: 100.0 % 10 10

            Line data    Source code
       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 "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           27 : do_disconnect (struct TALER_CRYPTO_CsDenominationHelper *dh)
      67              : {
      68           27 :   GNUNET_break (0 == close (dh->sock));
      69           27 :   dh->sock = -1;
      70           27 :   dh->synced = false;
      71           27 : }
      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         1876 : try_connect (struct TALER_CRYPTO_CsDenominationHelper *dh)
      83              : {
      84         1876 :   if (-1 != dh->sock)
      85         1849 :     return GNUNET_OK;
      86           27 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
      87              :               "Establishing connection!\n");
      88           27 :   dh->sock = socket (AF_UNIX,
      89              :                      SOCK_STREAM,
      90              :                      0);
      91           27 :   if (-1 == dh->sock)
      92              :   {
      93            0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
      94              :                          "socket");
      95            0 :     return GNUNET_SYSERR;
      96              :   }
      97           27 :   if (0 !=
      98           27 :       connect (dh->sock,
      99           27 :                (const struct sockaddr *) &dh->sa,
     100              :                sizeof (dh->sa)))
     101              :   {
     102            1 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
     103              :                               "connect",
     104              :                               dh->sa.sun_path);
     105            1 :     do_disconnect (dh);
     106            1 :     return GNUNET_SYSERR;
     107              :   }
     108           26 :   TALER_CRYPTO_helper_cs_poll (dh);
     109           26 :   return GNUNET_OK;
     110              : }
     111              : 
     112              : 
     113              : struct TALER_CRYPTO_CsDenominationHelper *
     114           27 : 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           27 :   GNUNET_asprintf (&secname,
     125              :                    "%s-secmod-cs",
     126              :                    section);
     127           27 :   if (GNUNET_OK !=
     128           27 :       GNUNET_CONFIGURATION_get_value_filename (cfg,
     129              :                                                secname,
     130              :                                                "UNIXPATH",
     131              :                                                &unixpath))
     132              :   {
     133            0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     134              :                                secname,
     135              :                                "UNIXPATH");
     136            0 :     GNUNET_free (secname);
     137            0 :     return NULL;
     138              :   }
     139              :   /* we use >= here because we want the sun_path to always
     140              :      be 0-terminated */
     141           27 :   if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
     142              :   {
     143            0 :     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     144              :                                secname,
     145              :                                "UNIXPATH",
     146              :                                "path too long");
     147            0 :     GNUNET_free (unixpath);
     148            0 :     GNUNET_free (secname);
     149            0 :     return NULL;
     150              :   }
     151           27 :   GNUNET_free (secname);
     152           27 :   dh = GNUNET_new (struct TALER_CRYPTO_CsDenominationHelper);
     153           27 :   dh->dkc = dkc;
     154           27 :   dh->dkc_cls = dkc_cls;
     155           27 :   dh->sa.sun_family = AF_UNIX;
     156           27 :   strncpy (dh->sa.sun_path,
     157              :            unixpath,
     158              :            sizeof (dh->sa.sun_path) - 1);
     159           27 :   GNUNET_free (unixpath);
     160           27 :   dh->sock = -1;
     161           27 :   if (GNUNET_OK !=
     162           27 :       try_connect (dh))
     163              :   {
     164            1 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     165              :                 "Could not connect to %s. Will keep trying\n",
     166              :                 "taler-exchange-helper-secmod-cs");
     167              :   }
     168           27 :   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          283 : handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
     181              :                  const struct GNUNET_MessageHeader *hdr)
     182              : {
     183          283 :   const struct TALER_CRYPTO_CsKeyAvailableNotification *kan
     184              :     = (const struct TALER_CRYPTO_CsKeyAvailableNotification *) hdr;
     185          283 :   const char *buf = (const char *) &kan[1];
     186              :   const char *section_name;
     187              :   uint16_t snl;
     188              : 
     189          283 :   if (sizeof (*kan) > ntohs (hdr->size))
     190              :   {
     191            0 :     GNUNET_break_op (0);
     192            0 :     return GNUNET_SYSERR;
     193              :   }
     194          283 :   snl = ntohs (kan->section_name_len);
     195          283 :   if (ntohs (hdr->size) != sizeof (*kan) + snl)
     196              :   {
     197            0 :     GNUNET_break_op (0);
     198            0 :     return GNUNET_SYSERR;
     199              :   }
     200          283 :   if (0 == snl)
     201              :   {
     202            0 :     GNUNET_break_op (0);
     203            0 :     return GNUNET_SYSERR;
     204              :   }
     205          283 :   section_name = buf;
     206          283 :   if ('\0' != section_name[snl - 1])
     207              :   {
     208            0 :     GNUNET_break_op (0);
     209            0 :     return GNUNET_SYSERR;
     210              :   }
     211              : 
     212              :   {
     213              :     struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
     214              :     struct TALER_CsPubHashP h_cs;
     215              : 
     216          283 :     bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
     217          283 :     bsign_pub->cipher = GNUNET_CRYPTO_BSA_CS;
     218          283 :     bsign_pub->rc = 1;
     219          283 :     bsign_pub->details.cs_public_key = kan->denom_pub;
     220              : 
     221          283 :     GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
     222              :                         sizeof (bsign_pub->details.cs_public_key),
     223              :                         &bsign_pub->pub_key_hash);
     224          283 :     h_cs.hash = bsign_pub->pub_key_hash;
     225          283 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     226              :                 "Received CS key %s (%s)\n",
     227              :                 GNUNET_h2s (&h_cs.hash),
     228              :                 section_name);
     229          283 :     if (GNUNET_OK !=
     230          283 :         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            0 :       GNUNET_break_op (0);
     239            0 :       GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
     240            0 :       return GNUNET_SYSERR;
     241              :     }
     242          283 :     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          283 :     GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
     251              :   }
     252          283 :   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            3 : handle_mt_purge (struct TALER_CRYPTO_CsDenominationHelper *dh,
     265              :                  const struct GNUNET_MessageHeader *hdr)
     266              : {
     267            3 :   const struct TALER_CRYPTO_CsKeyPurgeNotification *pn
     268              :     = (const struct TALER_CRYPTO_CsKeyPurgeNotification *) hdr;
     269              : 
     270            3 :   if (sizeof (*pn) != ntohs (hdr->size))
     271              :   {
     272            0 :     GNUNET_break_op (0);
     273            0 :     return GNUNET_SYSERR;
     274              :   }
     275            3 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     276              :               "Received revocation of denomination key %s\n",
     277              :               GNUNET_h2s (&pn->h_cs.hash));
     278            3 :   dh->dkc (dh->dkc_cls,
     279              :            NULL,
     280            3 :            GNUNET_TIME_UNIT_ZERO_TS,
     281            3 :            GNUNET_TIME_UNIT_ZERO,
     282              :            &pn->h_cs,
     283              :            NULL,
     284              :            NULL,
     285              :            NULL);
     286            3 :   return GNUNET_OK;
     287              : }
     288              : 
     289              : 
     290              : void
     291          738 : TALER_CRYPTO_helper_cs_poll (struct TALER_CRYPTO_CsDenominationHelper *dh)
     292              : {
     293              :   char buf[UINT16_MAX];
     294          738 :   size_t off = 0;
     295          738 :   unsigned int retry_limit = 3;
     296          738 :   const struct GNUNET_MessageHeader *hdr
     297              :     = (const struct GNUNET_MessageHeader *) buf;
     298              : 
     299          738 :   if (GNUNET_OK !=
     300          738 :       try_connect (dh))
     301            0 :     return; /* give up */
     302              :   while (1)
     303           34 :   {
     304              :     uint16_t msize;
     305              :     ssize_t ret;
     306              : 
     307          772 :     ret = recv (dh->sock,
     308              :                 buf + off,
     309              :                 sizeof (buf) - off,
     310          772 :                 (dh->synced && (0 == off))
     311              :                 ? MSG_DONTWAIT
     312              :                 : 0);
     313          772 :     if (ret < 0)
     314              :     {
     315          738 :       if (EINTR == errno)
     316            0 :         continue;
     317          738 :       if (EAGAIN == errno)
     318              :       {
     319          738 :         GNUNET_assert (dh->synced);
     320          738 :         GNUNET_assert (0 == off);
     321          738 :         break;
     322              :       }
     323            0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     324              :                            "recv");
     325            0 :       do_disconnect (dh);
     326            0 :       if (0 == retry_limit)
     327            0 :         return; /* give up */
     328            0 :       if (GNUNET_OK !=
     329            0 :           try_connect (dh))
     330            0 :         return; /* give up */
     331            0 :       retry_limit--;
     332            0 :       continue;
     333              :     }
     334           34 :     if (0 == ret)
     335              :     {
     336            0 :       GNUNET_break (0 == off);
     337            0 :       return;
     338              :     }
     339           34 :     off += ret;
     340          346 : more:
     341          346 :     if (off < sizeof (struct GNUNET_MessageHeader))
     342           34 :       continue;
     343          312 :     msize = ntohs (hdr->size);
     344          312 :     if (off < msize)
     345            0 :       continue;
     346          312 :     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          312 :     switch (ntohs (hdr->type))
     351              :     {
     352          283 :     case TALER_HELPER_CS_MT_AVAIL:
     353          283 :       if (GNUNET_OK !=
     354          283 :           handle_mt_avail (dh,
     355              :                            hdr))
     356              :       {
     357            0 :         GNUNET_break_op (0);
     358            0 :         do_disconnect (dh);
     359            0 :         return;
     360              :       }
     361          283 :       break;
     362            3 :     case TALER_HELPER_CS_MT_PURGE:
     363            3 :       if (GNUNET_OK !=
     364            3 :           handle_mt_purge (dh,
     365              :                            hdr))
     366              :       {
     367            0 :         GNUNET_break_op (0);
     368            0 :         do_disconnect (dh);
     369            0 :         return;
     370              :       }
     371            3 :       break;
     372           26 :     case TALER_HELPER_CS_SYNCED:
     373           26 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     374              :                   "Now synchronized with CS helper\n");
     375           26 :       dh->synced = true;
     376           26 :       break;
     377            0 :     default:
     378            0 :       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            0 :       GNUNET_break_op (0);
     383            0 :       do_disconnect (dh);
     384            0 :       return;
     385              :     }
     386          312 :     memmove (buf,
     387          312 :              &buf[msize],
     388              :              off - msize);
     389          312 :     off -= msize;
     390          312 :     goto more;
     391              :   }
     392              : }
     393              : 
     394              : 
     395              : void
     396            3 : TALER_CRYPTO_helper_cs_revoke (
     397              :   struct TALER_CRYPTO_CsDenominationHelper *dh,
     398              :   const struct TALER_CsPubHashP *h_cs)
     399              : {
     400            3 :   struct TALER_CRYPTO_CsRevokeRequest rr = {
     401            3 :     .header.size = htons (sizeof (rr)),
     402            3 :     .header.type = htons (TALER_HELPER_CS_MT_REQ_REVOKE),
     403              :     .h_cs = *h_cs
     404              :   };
     405              : 
     406            3 :   if (GNUNET_OK !=
     407            3 :       try_connect (dh))
     408            0 :     return; /* give up */
     409            3 :   if (GNUNET_OK !=
     410            3 :       TALER_crypto_helper_send_all (dh->sock,
     411              :                                     &rr,
     412              :                                     sizeof (rr)))
     413              :   {
     414            0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     415              :                          "send");
     416            0 :     do_disconnect (dh);
     417            0 :     return;
     418              :   }
     419            3 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     420              :               "Requested revocation of denomination key %s\n",
     421              :               GNUNET_h2s (&h_cs->hash));
     422              : }
     423              : 
     424              : 
     425              : enum TALER_ErrorCode
     426          959 : TALER_CRYPTO_helper_cs_batch_sign (
     427              :   struct TALER_CRYPTO_CsDenominationHelper *dh,
     428              :   unsigned int reqs_length,
     429              :   const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
     430              :   bool for_melt,
     431              :   struct TALER_BlindedDenominationSignature bss[static reqs_length])
     432          959 : {
     433          959 :   enum TALER_ErrorCode ec = TALER_EC_INVALID;
     434              :   unsigned int rpos;
     435              :   unsigned int rend;
     436              :   unsigned int wpos;
     437              : 
     438          959 :   memset (bss,
     439              :           0,
     440              :           sizeof (*bss) * reqs_length);
     441          959 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     442              :               "Starting signature process\n");
     443          959 :   if (GNUNET_OK !=
     444          959 :       try_connect (dh))
     445              :   {
     446            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     447              :                 "Failed to connect to helper\n");
     448            0 :     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     449              :   }
     450              : 
     451          959 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     452              :               "Requesting %u signatures\n",
     453              :               reqs_length);
     454          959 :   rpos = 0;
     455          959 :   rend = 0;
     456          959 :   wpos = 0;
     457         1918 :   while (rpos < reqs_length)
     458              :   {
     459          959 :     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
     460              : 
     461         2111 :     while ( (rend < reqs_length) &&
     462         1152 :             (mlen + sizeof (struct TALER_CRYPTO_CsSignRequestMessage)
     463              :              < UINT16_MAX) )
     464              :     {
     465         1152 :       mlen += sizeof (struct TALER_CRYPTO_CsSignRequestMessage);
     466         1152 :       rend++;
     467              :     }
     468          959 :     {
     469          959 :       char obuf[mlen] GNUNET_ALIGN;
     470          959 :       struct TALER_CRYPTO_BatchSignRequest *bsr
     471              :         = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
     472              :       void *wbuf;
     473              : 
     474          959 :       bsr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_SIGN);
     475          959 :       bsr->header.size = htons (mlen);
     476          959 :       bsr->batch_size = htonl (rend - rpos);
     477          959 :       wbuf = &bsr[1];
     478         2111 :       for (unsigned int i = rpos; i<rend; i++)
     479              :       {
     480         1152 :         struct TALER_CRYPTO_CsSignRequestMessage *csm = wbuf;
     481         1152 :         const struct TALER_CRYPTO_CsSignRequest *csr = &reqs[i];
     482              : 
     483         1152 :         csm->header.size = htons (sizeof (*csm));
     484         1152 :         csm->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
     485         1152 :         csm->for_melt = htonl (for_melt ? 1 : 0);
     486         1152 :         csm->h_cs = *csr->h_cs;
     487         1152 :         csm->message = *csr->blinded_planchet;
     488         1152 :         wbuf += sizeof (*csm);
     489              :       }
     490          959 :       GNUNET_assert (wbuf == &obuf[mlen]);
     491          959 :       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     492              :                   "Sending batch request [%u-%u)\n",
     493              :                   rpos,
     494              :                   rend);
     495          959 :       if (GNUNET_OK !=
     496          959 :           TALER_crypto_helper_send_all (dh->sock,
     497              :                                         obuf,
     498          959 :                                         sizeof (obuf)))
     499              :       {
     500            0 :         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     501              :                              "send");
     502            0 :         do_disconnect (dh);
     503            0 :         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     504              :       }
     505              :     } /* end of obuf scope */
     506          959 :     rpos = rend;
     507              :     {
     508              :       char buf[UINT16_MAX];
     509          959 :       size_t off = 0;
     510          959 :       const struct GNUNET_MessageHeader *hdr
     511              :         = (const struct GNUNET_MessageHeader *) buf;
     512          959 :       bool finished = false;
     513              : 
     514              :       while (1)
     515         1053 :       {
     516              :         uint16_t msize;
     517              :         ssize_t ret;
     518              : 
     519         2012 :         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     520              :                     "Awaiting reply at %u (up to %u)\n",
     521              :                     wpos,
     522              :                     rend);
     523         2971 :         ret = recv (dh->sock,
     524         2012 :                     &buf[off],
     525              :                     sizeof (buf) - off,
     526          959 :                     (finished && (0 == off))
     527              :                   ? MSG_DONTWAIT
     528              :                   : 0);
     529         2012 :         if (ret < 0)
     530              :         {
     531          959 :           if (EINTR == errno)
     532            0 :             continue;
     533          959 :           if (EAGAIN == errno)
     534              :           {
     535          959 :             GNUNET_assert (finished);
     536          959 :             GNUNET_assert (0 == off);
     537          959 :             break;
     538              :           }
     539            0 :           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     540              :                                "recv");
     541            0 :           do_disconnect (dh);
     542            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     543              :         }
     544         1053 :         if (0 == ret)
     545              :         {
     546            0 :           GNUNET_break (0 == off);
     547            0 :           if (! finished)
     548            0 :             return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     549            0 :           if (TALER_EC_NONE == ec)
     550            0 :             break;
     551            0 :           return ec;
     552              :         }
     553         1053 :         off += ret;
     554         2205 : more:
     555         2205 :         if (off < sizeof (struct GNUNET_MessageHeader))
     556         1053 :           continue;
     557         1152 :         msize = ntohs (hdr->size);
     558         1152 :         if (off < msize)
     559            0 :           continue;
     560         1152 :         switch (ntohs (hdr->type))
     561              :         {
     562         1149 :         case TALER_HELPER_CS_MT_RES_SIGNATURE:
     563         1149 :           if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
     564              :           {
     565            0 :             GNUNET_break_op (0);
     566            0 :             do_disconnect (dh);
     567            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     568              :           }
     569         1149 :           if (finished)
     570              :           {
     571            0 :             GNUNET_break_op (0);
     572            0 :             do_disconnect (dh);
     573            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     574              :           }
     575              :           {
     576         1149 :             const struct TALER_CRYPTO_SignResponse *sr =
     577              :               (const struct TALER_CRYPTO_SignResponse *) buf;
     578              :             struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
     579         1149 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     580              :                         "Received %u signature\n",
     581              :                         wpos);
     582         1149 :             blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
     583         1149 :             blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
     584         1149 :             blinded_sig->rc = 1;
     585         1149 :             blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
     586         1149 :             blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
     587              : 
     588         1149 :             bss[wpos].blinded_sig = blinded_sig;
     589         1149 :             wpos++;
     590         1149 :             if (wpos == rend)
     591              :             {
     592          956 :               if (TALER_EC_INVALID == ec)
     593          956 :                 ec = TALER_EC_NONE;
     594          956 :               finished = true;
     595              :             }
     596         1149 :             break;
     597              :           }
     598              : 
     599            3 :         case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
     600            3 :           if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
     601              :           {
     602            0 :             GNUNET_break_op (0);
     603            0 :             do_disconnect (dh);
     604            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     605              :           }
     606              :           {
     607            3 :             const struct TALER_CRYPTO_SignFailure *sf =
     608              :               (const struct TALER_CRYPTO_SignFailure *) buf;
     609              : 
     610            3 :             ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
     611            3 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     612              :                         "Signing %u failed with status %d!\n",
     613              :                         wpos,
     614              :                         ec);
     615            3 :             wpos++;
     616            3 :             if (wpos == rend)
     617              :             {
     618            3 :               finished = true;
     619              :             }
     620            3 :             break;
     621              :           }
     622            0 :         case TALER_HELPER_CS_MT_AVAIL:
     623            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     624              :                       "Received new key!\n");
     625            0 :           if (GNUNET_OK !=
     626            0 :               handle_mt_avail (dh,
     627              :                                hdr))
     628              :           {
     629            0 :             GNUNET_break_op (0);
     630            0 :             do_disconnect (dh);
     631            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     632              :           }
     633            0 :           break; /* while(1) loop ensures we recvfrom() again */
     634            0 :         case TALER_HELPER_CS_MT_PURGE:
     635            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     636              :                       "Received revocation!\n");
     637            0 :           if (GNUNET_OK !=
     638            0 :               handle_mt_purge (dh,
     639              :                                hdr))
     640              :           {
     641            0 :             GNUNET_break_op (0);
     642            0 :             do_disconnect (dh);
     643            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     644              :           }
     645            0 :           break; /* while(1) loop ensures we recvfrom() again */
     646            0 :         case TALER_HELPER_CS_SYNCED:
     647            0 :           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     648              :                       "Synchronized add odd time with CS helper!\n");
     649            0 :           dh->synced = true;
     650            0 :           break;
     651            0 :         default:
     652            0 :           GNUNET_break_op (0);
     653            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     654              :                       "Received unexpected message of type %u\n",
     655              :                       ntohs (hdr->type));
     656            0 :           do_disconnect (dh);
     657            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     658              :         }
     659         1152 :         memmove (buf,
     660         1152 :                  &buf[msize],
     661              :                  off - msize);
     662         1152 :         off -= msize;
     663         1152 :         goto more;
     664              :       } /* while(1) */
     665              :     } /* scope */
     666              :   } /* while (rpos < cdrs_length) */
     667          959 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     668              :               "Existing with %u signatures and status %d\n",
     669              :               wpos,
     670              :               ec);
     671          959 :   return ec;
     672              : }
     673              : 
     674              : 
     675              : enum TALER_ErrorCode
     676          149 : TALER_CRYPTO_helper_cs_r_batch_derive (
     677              :   struct TALER_CRYPTO_CsDenominationHelper *dh,
     678              :   unsigned int cdrs_length,
     679              :   const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
     680              :   bool for_melt,
     681              :   struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length])
     682          149 : {
     683          149 :   enum TALER_ErrorCode ec = TALER_EC_INVALID;
     684              :   unsigned int rpos;
     685              :   unsigned int rend;
     686              :   unsigned int wpos;
     687              : 
     688          149 :   memset (crps,
     689              :           0,
     690              :           sizeof (*crps) * cdrs_length);
     691          149 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     692              :               "Starting R derivation process\n");
     693          149 :   if (GNUNET_OK !=
     694          149 :       try_connect (dh))
     695              :   {
     696            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     697              :                 "Failed to connect to helper\n");
     698            0 :     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     699              :   }
     700              : 
     701          149 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     702              :               "Requesting %u R pairs\n",
     703              :               cdrs_length);
     704          149 :   rpos = 0;
     705          149 :   rend = 0;
     706          149 :   wpos = 0;
     707          298 :   while (rpos < cdrs_length)
     708              :   {
     709          149 :     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchDeriveRequest);
     710              : 
     711         1119 :     while ( (rend < cdrs_length) &&
     712          970 :             (mlen + sizeof (struct TALER_CRYPTO_CsRDeriveRequest)
     713              :              < UINT16_MAX) )
     714              :     {
     715          970 :       mlen += sizeof (struct TALER_CRYPTO_CsRDeriveRequest);
     716          970 :       rend++;
     717              :     }
     718          149 :     {
     719          149 :       char obuf[mlen] GNUNET_ALIGN;
     720          149 :       struct TALER_CRYPTO_BatchDeriveRequest *bdr
     721              :         = (struct TALER_CRYPTO_BatchDeriveRequest *) obuf;
     722              :       void *wbuf;
     723              : 
     724          149 :       bdr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_RDERIVE);
     725          149 :       bdr->header.size = htons (mlen);
     726          149 :       bdr->batch_size = htonl (rend - rpos);
     727          149 :       wbuf = &bdr[1];
     728         1119 :       for (unsigned int i = rpos; i<rend; i++)
     729              :       {
     730          970 :         struct TALER_CRYPTO_CsRDeriveRequest *rdr = wbuf;
     731          970 :         const struct TALER_CRYPTO_CsDeriveRequest *cdr = &cdrs[i];
     732              : 
     733          970 :         rdr->header.size = htons (sizeof (*rdr));
     734          970 :         rdr->header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
     735          970 :         rdr->for_melt = htonl (for_melt ? 1 : 0);
     736          970 :         rdr->h_cs = *cdr->h_cs;
     737          970 :         rdr->nonce = *cdr->nonce;
     738          970 :         wbuf += sizeof (*rdr);
     739              :       }
     740          149 :       GNUNET_assert (wbuf == &obuf[mlen]);
     741          149 :       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     742              :                   "Sending batch request [%u-%u)\n",
     743              :                   rpos,
     744              :                   rend);
     745          149 :       if (GNUNET_OK !=
     746          149 :           TALER_crypto_helper_send_all (dh->sock,
     747              :                                         obuf,
     748          149 :                                         sizeof (obuf)))
     749              :       {
     750            0 :         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     751              :                              "send");
     752            0 :         do_disconnect (dh);
     753            0 :         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     754              :       }
     755              :     } /* end of obuf scope */
     756          149 :     rpos = rend;
     757              :     {
     758              :       char buf[UINT16_MAX];
     759          149 :       size_t off = 0;
     760          149 :       const struct GNUNET_MessageHeader *hdr
     761              :         = (const struct GNUNET_MessageHeader *) buf;
     762          149 :       bool finished = false;
     763              : 
     764              :       while (1)
     765          488 :       {
     766              :         uint16_t msize;
     767              :         ssize_t ret;
     768              : 
     769          637 :         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     770              :                     "Awaiting reply at %u (up to %u)\n",
     771              :                     wpos,
     772              :                     rend);
     773          786 :         ret = recv (dh->sock,
     774          637 :                     &buf[off],
     775              :                     sizeof (buf) - off,
     776          149 :                     (finished && (0 == off))
     777              :                   ? MSG_DONTWAIT
     778              :                   : 0);
     779          637 :         if (ret < 0)
     780              :         {
     781          149 :           if (EINTR == errno)
     782            0 :             continue;
     783          149 :           if (EAGAIN == errno)
     784              :           {
     785          149 :             GNUNET_assert (finished);
     786          149 :             GNUNET_assert (0 == off);
     787          149 :             break;
     788              :           }
     789            0 :           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     790              :                                "recv");
     791            0 :           do_disconnect (dh);
     792            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     793              :         }
     794          488 :         if (0 == ret)
     795              :         {
     796            0 :           GNUNET_break (0 == off);
     797            0 :           if (! finished)
     798            0 :             return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     799            0 :           if (TALER_EC_NONE == ec)
     800            0 :             break;
     801            0 :           return ec;
     802              :         }
     803          488 :         off += ret;
     804         1458 : more:
     805         1458 :         if (off < sizeof (struct GNUNET_MessageHeader))
     806          488 :           continue;
     807          970 :         msize = ntohs (hdr->size);
     808          970 :         if (off < msize)
     809            0 :           continue;
     810          970 :         switch (ntohs (hdr->type))
     811              :         {
     812          357 :         case TALER_HELPER_CS_MT_RES_RDERIVE:
     813          357 :           if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
     814              :           {
     815            0 :             GNUNET_break_op (0);
     816            0 :             do_disconnect (dh);
     817            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     818              :           }
     819          357 :           if (finished)
     820              :           {
     821            0 :             GNUNET_break_op (0);
     822            0 :             do_disconnect (dh);
     823            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     824              :           }
     825              :           {
     826          357 :             const struct TALER_CRYPTO_RDeriveResponse *rdr =
     827              :               (const struct TALER_CRYPTO_RDeriveResponse *) buf;
     828              : 
     829          357 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     830              :                         "Received %u R pair\n",
     831              :                         wpos);
     832          357 :             crps[wpos] = rdr->r_pub;
     833          357 :             wpos++;
     834          357 :             if (wpos == rend)
     835              :             {
     836          116 :               if (TALER_EC_INVALID == ec)
     837          116 :                 ec = TALER_EC_NONE;
     838          116 :               finished = true;
     839              :             }
     840          357 :             break;
     841              :           }
     842          613 :         case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
     843          613 :           if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
     844              :           {
     845            0 :             GNUNET_break_op (0);
     846            0 :             do_disconnect (dh);
     847            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     848              :           }
     849              :           {
     850          613 :             const struct TALER_CRYPTO_RDeriveFailure *rdf =
     851              :               (const struct TALER_CRYPTO_RDeriveFailure *) buf;
     852              : 
     853          613 :             ec = (enum TALER_ErrorCode) (int) ntohl (rdf->ec);
     854          613 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     855              :                         "R derivation %u failed with status %d!\n",
     856              :                         wpos,
     857              :                         ec);
     858          613 :             wpos++;
     859          613 :             if (wpos == rend)
     860              :             {
     861           33 :               finished = true;
     862              :             }
     863          613 :             break;
     864              :           }
     865            0 :         case TALER_HELPER_CS_MT_AVAIL:
     866            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     867              :                       "Received new key!\n");
     868            0 :           if (GNUNET_OK !=
     869            0 :               handle_mt_avail (dh,
     870              :                                hdr))
     871              :           {
     872            0 :             GNUNET_break_op (0);
     873            0 :             do_disconnect (dh);
     874            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     875              :           }
     876            0 :           break; /* while(1) loop ensures we recvfrom() again */
     877            0 :         case TALER_HELPER_CS_MT_PURGE:
     878            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     879              :                       "Received revocation!\n");
     880            0 :           if (GNUNET_OK !=
     881            0 :               handle_mt_purge (dh,
     882              :                                hdr))
     883              :           {
     884            0 :             GNUNET_break_op (0);
     885            0 :             do_disconnect (dh);
     886            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     887              :           }
     888            0 :           break; /* while(1) loop ensures we recvfrom() again */
     889            0 :         case TALER_HELPER_CS_SYNCED:
     890            0 :           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     891              :                       "Synchronized add odd time with CS helper!\n");
     892            0 :           dh->synced = true;
     893            0 :           break;
     894            0 :         default:
     895            0 :           GNUNET_break_op (0);
     896            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     897              :                       "Received unexpected message of type %u\n",
     898              :                       ntohs (hdr->type));
     899            0 :           do_disconnect (dh);
     900            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     901              :         }
     902          970 :         memmove (buf,
     903          970 :                  &buf[msize],
     904              :                  off - msize);
     905          970 :         off -= msize;
     906          970 :         goto more;
     907              :       } /* while(1) */
     908              :     } /* scope */
     909              :   } /* while (rpos < cdrs_length) */
     910          149 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     911              :               "Existing with %u signatures and status %d\n",
     912              :               wpos,
     913              :               ec);
     914          149 :   return ec;
     915              : }
     916              : 
     917              : 
     918              : void
     919           27 : TALER_CRYPTO_helper_cs_disconnect (
     920              :   struct TALER_CRYPTO_CsDenominationHelper *dh)
     921              : {
     922           27 :   if (-1 != dh->sock)
     923           26 :     do_disconnect (dh);
     924           27 :   GNUNET_free (dh);
     925           27 : }
     926              : 
     927              : 
     928              : /* end of crypto_helper_cs.c */
        

Generated by: LCOV version 2.0-1