LCOV - code coverage report
Current view: top level - util - crypto_helper_cs.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 65.4 % 463 303
Test Date: 2026-09-11 18:55:36 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         1884 : try_connect (struct TALER_CRYPTO_CsDenominationHelper *dh)
      83              : {
      84         1884 :   if (-1 != dh->sock)
      85         1857 :     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          233 : handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
     181              :                  const struct GNUNET_MessageHeader *hdr)
     182              : {
     183          233 :   const struct TALER_CRYPTO_CsKeyAvailableNotification *kan
     184              :     = (const struct TALER_CRYPTO_CsKeyAvailableNotification *) hdr;
     185          233 :   const char *buf = (const char *) &kan[1];
     186              :   const char *section_name;
     187              :   uint32_t snl;
     188              : 
     189          233 :   if (sizeof (*kan) > ntohs (hdr->size))
     190              :   {
     191            0 :     GNUNET_break_op (0);
     192            0 :     return GNUNET_SYSERR;
     193              :   }
     194          233 :   snl = ntohl (kan->section_name_len);
     195          233 :   if (ntohs (hdr->size) != sizeof (*kan) + snl)
     196              :   {
     197            0 :     GNUNET_break_op (0);
     198            0 :     return GNUNET_SYSERR;
     199              :   }
     200          233 :   if (0 == snl)
     201              :   {
     202            0 :     GNUNET_break_op (0);
     203            0 :     return GNUNET_SYSERR;
     204              :   }
     205          233 :   section_name = buf;
     206          233 :   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          233 :     bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
     217          233 :     bsign_pub->cipher = GNUNET_CRYPTO_BSA_CS;
     218          233 :     bsign_pub->rc = 1;
     219          233 :     bsign_pub->details.cs_public_key = kan->denom_pub;
     220              : 
     221          233 :     GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
     222              :                         sizeof (bsign_pub->details.cs_public_key),
     223              :                         &bsign_pub->pub_key_hash);
     224          233 :     h_cs.hash = bsign_pub->pub_key_hash;
     225          233 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     226              :                 "Received CS key %s (%s)\n",
     227              :                 GNUNET_h2s (&h_cs.hash),
     228              :                 section_name);
     229          233 :     if (GNUNET_OK !=
     230          233 :         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          233 :     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          233 :     GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
     251              :   }
     252          233 :   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           36 :   {
     304              :     uint16_t msize;
     305              :     ssize_t ret;
     306              : 
     307          774 :     ret = recv (dh->sock,
     308              :                 buf + off,
     309              :                 sizeof (buf) - off,
     310          774 :                 (dh->synced && (0 == off))
     311              :                 ? MSG_DONTWAIT
     312              :                 : 0);
     313          774 :     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           36 :     if (0 == ret)
     335              :     {
     336            0 :       GNUNET_break (0 == off);
     337            0 :       return;
     338              :     }
     339           36 :     off += ret;
     340          298 : more:
     341          298 :     if (off < sizeof (struct GNUNET_MessageHeader))
     342           36 :       continue;
     343          262 :     msize = ntohs (hdr->size);
     344          262 :     if (msize < sizeof (struct GNUNET_MessageHeader))
     345              :     {
     346            0 :       GNUNET_break_op (0);
     347            0 :       do_disconnect (dh);
     348            0 :       return;
     349              :     }
     350          262 :     if (off < msize)
     351            0 :       continue;
     352          262 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     353              :                 "Received message of type %u and length %u\n",
     354              :                 (unsigned int) ntohs (hdr->type),
     355              :                 (unsigned int) msize);
     356          262 :     switch (ntohs (hdr->type))
     357              :     {
     358          233 :     case TALER_HELPER_CS_MT_AVAIL:
     359          233 :       if (GNUNET_OK !=
     360          233 :           handle_mt_avail (dh,
     361              :                            hdr))
     362              :       {
     363            0 :         GNUNET_break_op (0);
     364            0 :         do_disconnect (dh);
     365            0 :         return;
     366              :       }
     367          233 :       break;
     368            3 :     case TALER_HELPER_CS_MT_PURGE:
     369            3 :       if (GNUNET_OK !=
     370            3 :           handle_mt_purge (dh,
     371              :                            hdr))
     372              :       {
     373            0 :         GNUNET_break_op (0);
     374            0 :         do_disconnect (dh);
     375            0 :         return;
     376              :       }
     377            3 :       break;
     378           26 :     case TALER_HELPER_CS_SYNCED:
     379           26 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     380              :                   "Now synchronized with CS helper\n");
     381           26 :       dh->synced = true;
     382           26 :       break;
     383            0 :     default:
     384            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     385              :                   "Received unexpected message of type %d (len: %u)\n",
     386              :                   (unsigned int) ntohs (hdr->type),
     387              :                   (unsigned int) msize);
     388            0 :       GNUNET_break_op (0);
     389            0 :       do_disconnect (dh);
     390            0 :       return;
     391              :     }
     392          262 :     memmove (buf,
     393          262 :              &buf[msize],
     394              :              off - msize);
     395          262 :     off -= msize;
     396          262 :     goto more;
     397              :   }
     398              : }
     399              : 
     400              : 
     401              : void
     402            3 : TALER_CRYPTO_helper_cs_revoke (
     403              :   struct TALER_CRYPTO_CsDenominationHelper *dh,
     404              :   const struct TALER_CsPubHashP *h_cs)
     405              : {
     406            3 :   struct TALER_CRYPTO_CsRevokeRequest rr = {
     407            3 :     .header.size = htons (sizeof (rr)),
     408            3 :     .header.type = htons (TALER_HELPER_CS_MT_REQ_REVOKE),
     409              :     .h_cs = *h_cs
     410              :   };
     411              : 
     412            3 :   if (GNUNET_OK !=
     413            3 :       try_connect (dh))
     414            0 :     return; /* give up */
     415            3 :   if (GNUNET_OK !=
     416            3 :       TALER_crypto_helper_send_all (dh->sock,
     417              :                                     &rr,
     418              :                                     sizeof (rr)))
     419              :   {
     420            0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     421              :                          "send");
     422            0 :     do_disconnect (dh);
     423            0 :     return;
     424              :   }
     425            3 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     426              :               "Requested revocation of denomination key %s\n",
     427              :               GNUNET_h2s (&h_cs->hash));
     428              : }
     429              : 
     430              : 
     431              : enum TALER_ErrorCode
     432          959 : TALER_CRYPTO_helper_cs_batch_sign (
     433              :   struct TALER_CRYPTO_CsDenominationHelper *dh,
     434              :   unsigned int reqs_length,
     435              :   const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
     436              :   bool for_melt,
     437              :   struct TALER_BlindedDenominationSignature bss[static reqs_length])
     438          959 : {
     439          959 :   enum TALER_ErrorCode ec = TALER_EC_INVALID;
     440              :   unsigned int rpos;
     441              :   unsigned int rend;
     442              :   unsigned int wpos;
     443              : 
     444          959 :   memset (bss,
     445              :           0,
     446              :           sizeof (*bss) * reqs_length);
     447          959 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     448              :               "Starting signature process\n");
     449          959 :   if (GNUNET_OK !=
     450          959 :       try_connect (dh))
     451              :   {
     452            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     453              :                 "Failed to connect to helper\n");
     454            0 :     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     455              :   }
     456              : 
     457          959 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     458              :               "Requesting %u signatures\n",
     459              :               reqs_length);
     460          959 :   rpos = 0;
     461          959 :   rend = 0;
     462          959 :   wpos = 0;
     463         1918 :   while (rpos < reqs_length)
     464              :   {
     465          959 :     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
     466              : 
     467         2111 :     while ( (rend < reqs_length) &&
     468         1152 :             (mlen + sizeof (struct TALER_CRYPTO_CsSignRequestMessage)
     469              :              < UINT16_MAX) )
     470              :     {
     471         1152 :       mlen += sizeof (struct TALER_CRYPTO_CsSignRequestMessage);
     472         1152 :       rend++;
     473              :     }
     474          959 :     {
     475          959 :       char obuf[mlen] GNUNET_ALIGN;
     476          959 :       struct TALER_CRYPTO_BatchSignRequest *bsr
     477              :         = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
     478              :       void *wbuf;
     479              : 
     480          959 :       bsr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_SIGN);
     481          959 :       bsr->header.size = htons (mlen);
     482          959 :       bsr->batch_size = htonl (rend - rpos);
     483          959 :       wbuf = &bsr[1];
     484         2111 :       for (unsigned int i = rpos; i<rend; i++)
     485              :       {
     486         1152 :         struct TALER_CRYPTO_CsSignRequestMessage *csm = wbuf;
     487         1152 :         const struct TALER_CRYPTO_CsSignRequest *csr = &reqs[i];
     488              : 
     489         1152 :         csm->header.size = htons (sizeof (*csm));
     490         1152 :         csm->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
     491         1152 :         csm->for_melt = htonl (for_melt ? 1 : 0);
     492         1152 :         csm->h_cs = *csr->h_cs;
     493         1152 :         csm->message = *csr->blinded_planchet;
     494         1152 :         wbuf += sizeof (*csm);
     495              :       }
     496          959 :       GNUNET_assert (wbuf == &obuf[mlen]);
     497          959 :       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     498              :                   "Sending batch request [%u-%u)\n",
     499              :                   rpos,
     500              :                   rend);
     501          959 :       if (GNUNET_OK !=
     502          959 :           TALER_crypto_helper_send_all (dh->sock,
     503              :                                         obuf,
     504          959 :                                         sizeof (obuf)))
     505              :       {
     506            0 :         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     507              :                              "send");
     508            0 :         do_disconnect (dh);
     509            0 :         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     510              :       }
     511              :     } /* end of obuf scope */
     512          959 :     rpos = rend;
     513              :     {
     514              :       char buf[UINT16_MAX];
     515          959 :       size_t off = 0;
     516          959 :       const struct GNUNET_MessageHeader *hdr
     517              :         = (const struct GNUNET_MessageHeader *) buf;
     518          959 :       bool finished = false;
     519              : 
     520              :       while (1)
     521         1041 :       {
     522              :         uint16_t msize;
     523              :         ssize_t ret;
     524              : 
     525         2000 :         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     526              :                     "Awaiting reply at %u (up to %u)\n",
     527              :                     wpos,
     528              :                     rend);
     529         2959 :         ret = recv (dh->sock,
     530         2000 :                     &buf[off],
     531              :                     sizeof (buf) - off,
     532          959 :                     (finished && (0 == off))
     533              :                   ? MSG_DONTWAIT
     534              :                   : 0);
     535         2000 :         if (ret < 0)
     536              :         {
     537          959 :           if (EINTR == errno)
     538            0 :             continue;
     539          959 :           if (EAGAIN == errno)
     540              :           {
     541          959 :             GNUNET_assert (finished);
     542          959 :             GNUNET_assert (0 == off);
     543          959 :             break;
     544              :           }
     545            0 :           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     546              :                                "recv");
     547            0 :           do_disconnect (dh);
     548            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     549              :         }
     550         1041 :         if (0 == ret)
     551              :         {
     552            0 :           GNUNET_break (0 == off);
     553            0 :           if (! finished)
     554            0 :             return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     555            0 :           if (TALER_EC_NONE == ec)
     556            0 :             break;
     557            0 :           return ec;
     558              :         }
     559         1041 :         off += ret;
     560         2193 : more:
     561         2193 :         if (off < sizeof (struct GNUNET_MessageHeader))
     562         1041 :           continue;
     563         1152 :         msize = ntohs (hdr->size);
     564         1152 :         if (msize < sizeof (struct GNUNET_MessageHeader))
     565              :         {
     566            0 :           GNUNET_break_op (0);
     567            0 :           do_disconnect (dh);
     568            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     569              :         }
     570         1152 :         if (off < msize)
     571            0 :           continue;
     572         1152 :         switch (ntohs (hdr->type))
     573              :         {
     574         1149 :         case TALER_HELPER_CS_MT_RES_SIGNATURE:
     575         1149 :           if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
     576              :           {
     577            0 :             GNUNET_break_op (0);
     578            0 :             do_disconnect (dh);
     579            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     580              :           }
     581         1149 :           if (finished)
     582              :           {
     583            0 :             GNUNET_break_op (0);
     584            0 :             do_disconnect (dh);
     585            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     586              :           }
     587              :           {
     588         1149 :             const struct TALER_CRYPTO_SignResponse *sr =
     589              :               (const struct TALER_CRYPTO_SignResponse *) buf;
     590              :             struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
     591         1149 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     592              :                         "Received %u signature\n",
     593              :                         wpos);
     594         1149 :             blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
     595         1149 :             blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
     596         1149 :             blinded_sig->rc = 1;
     597         1149 :             blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
     598         1149 :             blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
     599              : 
     600         1149 :             bss[wpos].blinded_sig = blinded_sig;
     601         1149 :             wpos++;
     602         1149 :             if (wpos == rend)
     603              :             {
     604          956 :               if (TALER_EC_INVALID == ec)
     605          956 :                 ec = TALER_EC_NONE;
     606          956 :               finished = true;
     607              :             }
     608         1149 :             break;
     609              :           }
     610              : 
     611            3 :         case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
     612            3 :           if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
     613              :           {
     614            0 :             GNUNET_break_op (0);
     615            0 :             do_disconnect (dh);
     616            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     617              :           }
     618              :           {
     619            3 :             const struct TALER_CRYPTO_SignFailure *sf =
     620              :               (const struct TALER_CRYPTO_SignFailure *) buf;
     621              : 
     622            3 :             ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
     623            3 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     624              :                         "Signing %u failed with status %d!\n",
     625              :                         wpos,
     626              :                         ec);
     627            3 :             wpos++;
     628            3 :             if (wpos == rend)
     629              :             {
     630            3 :               finished = true;
     631              :             }
     632            3 :             break;
     633              :           }
     634            0 :         case TALER_HELPER_CS_MT_AVAIL:
     635            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     636              :                       "Received new key!\n");
     637            0 :           if (GNUNET_OK !=
     638            0 :               handle_mt_avail (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_MT_PURGE:
     647            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     648              :                       "Received revocation!\n");
     649            0 :           if (GNUNET_OK !=
     650            0 :               handle_mt_purge (dh,
     651              :                                hdr))
     652              :           {
     653            0 :             GNUNET_break_op (0);
     654            0 :             do_disconnect (dh);
     655            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     656              :           }
     657            0 :           break; /* while(1) loop ensures we recvfrom() again */
     658            0 :         case TALER_HELPER_CS_SYNCED:
     659            0 :           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     660              :                       "Synchronized add odd time with CS helper!\n");
     661            0 :           dh->synced = true;
     662            0 :           break;
     663            0 :         default:
     664            0 :           GNUNET_break_op (0);
     665            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     666              :                       "Received unexpected message of type %u\n",
     667              :                       ntohs (hdr->type));
     668            0 :           do_disconnect (dh);
     669            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     670              :         }
     671         1152 :         memmove (buf,
     672         1152 :                  &buf[msize],
     673              :                  off - msize);
     674         1152 :         off -= msize;
     675         1152 :         goto more;
     676              :       } /* while(1) */
     677              :     } /* scope */
     678              :   } /* while (rpos < cdrs_length) */
     679          959 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     680              :               "Existing with %u signatures and status %d\n",
     681              :               wpos,
     682              :               ec);
     683          959 :   return ec;
     684              : }
     685              : 
     686              : 
     687              : enum TALER_ErrorCode
     688          157 : TALER_CRYPTO_helper_cs_r_batch_derive (
     689              :   struct TALER_CRYPTO_CsDenominationHelper *dh,
     690              :   unsigned int cdrs_length,
     691              :   const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
     692              :   bool for_melt,
     693              :   struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length])
     694          157 : {
     695          157 :   enum TALER_ErrorCode ec = TALER_EC_INVALID;
     696              :   unsigned int rpos;
     697              :   unsigned int rend;
     698              :   unsigned int wpos;
     699              : 
     700          157 :   memset (crps,
     701              :           0,
     702              :           sizeof (*crps) * cdrs_length);
     703          157 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     704              :               "Starting R derivation process\n");
     705          157 :   if (GNUNET_OK !=
     706          157 :       try_connect (dh))
     707              :   {
     708            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     709              :                 "Failed to connect to helper\n");
     710            0 :     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     711              :   }
     712              : 
     713          157 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     714              :               "Requesting %u R pairs\n",
     715              :               cdrs_length);
     716          157 :   rpos = 0;
     717          157 :   rend = 0;
     718          157 :   wpos = 0;
     719          314 :   while (rpos < cdrs_length)
     720              :   {
     721          157 :     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchDeriveRequest);
     722              : 
     723         1135 :     while ( (rend < cdrs_length) &&
     724          978 :             (mlen + sizeof (struct TALER_CRYPTO_CsRDeriveRequest)
     725              :              < UINT16_MAX) )
     726              :     {
     727          978 :       mlen += sizeof (struct TALER_CRYPTO_CsRDeriveRequest);
     728          978 :       rend++;
     729              :     }
     730          157 :     {
     731          157 :       char obuf[mlen] GNUNET_ALIGN;
     732          157 :       struct TALER_CRYPTO_BatchDeriveRequest *bdr
     733              :         = (struct TALER_CRYPTO_BatchDeriveRequest *) obuf;
     734              :       void *wbuf;
     735              : 
     736          157 :       bdr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_RDERIVE);
     737          157 :       bdr->header.size = htons (mlen);
     738          157 :       bdr->batch_size = htonl (rend - rpos);
     739          157 :       wbuf = &bdr[1];
     740         1135 :       for (unsigned int i = rpos; i<rend; i++)
     741              :       {
     742          978 :         struct TALER_CRYPTO_CsRDeriveRequest *rdr = wbuf;
     743          978 :         const struct TALER_CRYPTO_CsDeriveRequest *cdr = &cdrs[i];
     744              : 
     745          978 :         rdr->header.size = htons (sizeof (*rdr));
     746          978 :         rdr->header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
     747          978 :         rdr->for_melt = htonl (for_melt ? 1 : 0);
     748          978 :         rdr->h_cs = *cdr->h_cs;
     749          978 :         rdr->nonce = *cdr->nonce;
     750          978 :         wbuf += sizeof (*rdr);
     751              :       }
     752          157 :       GNUNET_assert (wbuf == &obuf[mlen]);
     753          157 :       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     754              :                   "Sending batch request [%u-%u)\n",
     755              :                   rpos,
     756              :                   rend);
     757          157 :       if (GNUNET_OK !=
     758          157 :           TALER_crypto_helper_send_all (dh->sock,
     759              :                                         obuf,
     760          157 :                                         sizeof (obuf)))
     761              :       {
     762            0 :         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     763              :                              "send");
     764            0 :         do_disconnect (dh);
     765            0 :         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     766              :       }
     767              :     } /* end of obuf scope */
     768          157 :     rpos = rend;
     769              :     {
     770              :       char buf[UINT16_MAX];
     771          157 :       size_t off = 0;
     772          157 :       const struct GNUNET_MessageHeader *hdr
     773              :         = (const struct GNUNET_MessageHeader *) buf;
     774          157 :       bool finished = false;
     775              : 
     776              :       while (1)
     777          451 :       {
     778              :         uint16_t msize;
     779              :         ssize_t ret;
     780              : 
     781          608 :         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     782              :                     "Awaiting reply at %u (up to %u)\n",
     783              :                     wpos,
     784              :                     rend);
     785          765 :         ret = recv (dh->sock,
     786          608 :                     &buf[off],
     787              :                     sizeof (buf) - off,
     788          157 :                     (finished && (0 == off))
     789              :                   ? MSG_DONTWAIT
     790              :                   : 0);
     791          608 :         if (ret < 0)
     792              :         {
     793          157 :           if (EINTR == errno)
     794            0 :             continue;
     795          157 :           if (EAGAIN == errno)
     796              :           {
     797          157 :             GNUNET_assert (finished);
     798          157 :             GNUNET_assert (0 == off);
     799          157 :             break;
     800              :           }
     801            0 :           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     802              :                                "recv");
     803            0 :           do_disconnect (dh);
     804            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     805              :         }
     806          451 :         if (0 == ret)
     807              :         {
     808            0 :           GNUNET_break (0 == off);
     809            0 :           if (! finished)
     810            0 :             return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     811            0 :           if (TALER_EC_NONE == ec)
     812            0 :             break;
     813            0 :           return ec;
     814              :         }
     815          451 :         off += ret;
     816         1429 : more:
     817         1429 :         if (off < sizeof (struct GNUNET_MessageHeader))
     818          451 :           continue;
     819          978 :         msize = ntohs (hdr->size);
     820          978 :         if (msize < sizeof (struct GNUNET_MessageHeader))
     821              :         {
     822            0 :           GNUNET_break_op (0);
     823            0 :           do_disconnect (dh);
     824            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     825              :         }
     826          978 :         if (off < msize)
     827            0 :           continue;
     828          978 :         switch (ntohs (hdr->type))
     829              :         {
     830          357 :         case TALER_HELPER_CS_MT_RES_RDERIVE:
     831          357 :           if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
     832              :           {
     833            0 :             GNUNET_break_op (0);
     834            0 :             do_disconnect (dh);
     835            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     836              :           }
     837          357 :           if (finished)
     838              :           {
     839            0 :             GNUNET_break_op (0);
     840            0 :             do_disconnect (dh);
     841            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     842              :           }
     843              :           {
     844          357 :             const struct TALER_CRYPTO_RDeriveResponse *rdr =
     845              :               (const struct TALER_CRYPTO_RDeriveResponse *) buf;
     846              : 
     847          357 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     848              :                         "Received %u R pair\n",
     849              :                         wpos);
     850          357 :             crps[wpos] = rdr->r_pub;
     851          357 :             wpos++;
     852          357 :             if (wpos == rend)
     853              :             {
     854          116 :               if (TALER_EC_INVALID == ec)
     855          116 :                 ec = TALER_EC_NONE;
     856          116 :               finished = true;
     857              :             }
     858          357 :             break;
     859              :           }
     860          621 :         case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
     861          621 :           if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
     862              :           {
     863            0 :             GNUNET_break_op (0);
     864            0 :             do_disconnect (dh);
     865            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     866              :           }
     867              :           {
     868          621 :             const struct TALER_CRYPTO_RDeriveFailure *rdf =
     869              :               (const struct TALER_CRYPTO_RDeriveFailure *) buf;
     870              : 
     871          621 :             ec = (enum TALER_ErrorCode) (int) ntohl (rdf->ec);
     872          621 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     873              :                         "R derivation %u failed with status %d!\n",
     874              :                         wpos,
     875              :                         ec);
     876          621 :             wpos++;
     877          621 :             if (wpos == rend)
     878              :             {
     879           41 :               finished = true;
     880              :             }
     881          621 :             break;
     882              :           }
     883            0 :         case TALER_HELPER_CS_MT_AVAIL:
     884            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     885              :                       "Received new key!\n");
     886            0 :           if (GNUNET_OK !=
     887            0 :               handle_mt_avail (dh,
     888              :                                hdr))
     889              :           {
     890            0 :             GNUNET_break_op (0);
     891            0 :             do_disconnect (dh);
     892            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     893              :           }
     894            0 :           break; /* while(1) loop ensures we recvfrom() again */
     895            0 :         case TALER_HELPER_CS_MT_PURGE:
     896            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     897              :                       "Received revocation!\n");
     898            0 :           if (GNUNET_OK !=
     899            0 :               handle_mt_purge (dh,
     900              :                                hdr))
     901              :           {
     902            0 :             GNUNET_break_op (0);
     903            0 :             do_disconnect (dh);
     904            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     905              :           }
     906            0 :           break; /* while(1) loop ensures we recvfrom() again */
     907            0 :         case TALER_HELPER_CS_SYNCED:
     908            0 :           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     909              :                       "Synchronized add odd time with CS helper!\n");
     910            0 :           dh->synced = true;
     911            0 :           break;
     912            0 :         default:
     913            0 :           GNUNET_break_op (0);
     914            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     915              :                       "Received unexpected message of type %u\n",
     916              :                       ntohs (hdr->type));
     917            0 :           do_disconnect (dh);
     918            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     919              :         }
     920          978 :         memmove (buf,
     921          978 :                  &buf[msize],
     922              :                  off - msize);
     923          978 :         off -= msize;
     924          978 :         goto more;
     925              :       } /* while(1) */
     926              :     } /* scope */
     927              :   } /* while (rpos < cdrs_length) */
     928          157 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     929              :               "Existing with %u signatures and status %d\n",
     930              :               wpos,
     931              :               ec);
     932          157 :   return ec;
     933              : }
     934              : 
     935              : 
     936              : void
     937           27 : TALER_CRYPTO_helper_cs_disconnect (
     938              :   struct TALER_CRYPTO_CsDenominationHelper *dh)
     939              : {
     940           27 :   if (-1 != dh->sock)
     941           26 :     do_disconnect (dh);
     942           27 :   GNUNET_free (dh);
     943           27 : }
     944              : 
     945              : 
     946              : /* end of crypto_helper_cs.c */
        

Generated by: LCOV version 2.0-1