LCOV - code coverage report
Current view: top level - util - crypto_helper_esign.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 60.1 % 263 158
Test Date: 2026-09-11 18:55:36 Functions: 100.0 % 9 9

            Line data    Source code
       1              : /*
       2              :   This file is part of TALER
       3              :   Copyright (C) 2020, 2021 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_esign.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_eddsa.h"
      25              : #include <poll.h>
      26              : #include "crypto_helper_common.h"
      27              : 
      28              : 
      29              : struct TALER_CRYPTO_ExchangeSignHelper
      30              : {
      31              :   /**
      32              :    * Function to call with updates to available key material.
      33              :    */
      34              :   TALER_CRYPTO_ExchangeKeyStatusCallback ekc;
      35              : 
      36              :   /**
      37              :    * Closure for @e ekc
      38              :    */
      39              :   void *ekc_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 reached the sync'ed state?
      54              :    */
      55              :   bool synced;
      56              : 
      57              : };
      58              : 
      59              : 
      60              : /**
      61              :  * Disconnect from the helper process.  Updates
      62              :  * @e sock field in @a esh.
      63              :  *
      64              :  * @param[in,out] esh handle to tear down connection of
      65              :  */
      66              : static void
      67           27 : do_disconnect (struct TALER_CRYPTO_ExchangeSignHelper *esh)
      68              : {
      69           27 :   GNUNET_break (0 == close (esh->sock));
      70           27 :   esh->sock = -1;
      71           27 :   esh->synced = false;
      72           27 : }
      73              : 
      74              : 
      75              : /**
      76              :  * Try to connect to the helper process.  Updates
      77              :  * @e sock field in @a esh.
      78              :  *
      79              :  * @param[in,out] esh handle to establish connection for
      80              :  * @return #GNUNET_OK on success
      81              :  */
      82              : static enum GNUNET_GenericReturnValue
      83         2807 : try_connect (struct TALER_CRYPTO_ExchangeSignHelper *esh)
      84              : {
      85         2807 :   if (-1 != esh->sock)
      86         2780 :     return GNUNET_OK;
      87           27 :   esh->sock = socket (AF_UNIX,
      88              :                       SOCK_STREAM,
      89              :                       0);
      90           27 :   if (-1 == esh->sock)
      91              :   {
      92            0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
      93              :                          "socket");
      94            0 :     return GNUNET_SYSERR;
      95              :   }
      96           27 :   if (0 !=
      97           27 :       connect (esh->sock,
      98           27 :                (const struct sockaddr *) &esh->sa,
      99              :                sizeof (esh->sa)))
     100              :   {
     101            1 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
     102              :                               "connect",
     103              :                               esh->sa.sun_path);
     104            1 :     do_disconnect (esh);
     105            1 :     return GNUNET_SYSERR;
     106              :   }
     107           26 :   return GNUNET_OK;
     108              : }
     109              : 
     110              : 
     111              : struct TALER_CRYPTO_ExchangeSignHelper *
     112           27 : TALER_CRYPTO_helper_esign_connect (
     113              :   const struct GNUNET_CONFIGURATION_Handle *cfg,
     114              :   const char *section,
     115              :   TALER_CRYPTO_ExchangeKeyStatusCallback ekc,
     116              :   void *ekc_cls)
     117              : {
     118              :   struct TALER_CRYPTO_ExchangeSignHelper *esh;
     119              :   char *unixpath;
     120              :   char *secname;
     121              : 
     122           27 :   GNUNET_asprintf (&secname,
     123              :                    "%s-secmod-eddsa",
     124              :                    section);
     125              : 
     126           27 :   if (GNUNET_OK !=
     127           27 :       GNUNET_CONFIGURATION_get_value_filename (cfg,
     128              :                                                secname,
     129              :                                                "UNIXPATH",
     130              :                                                &unixpath))
     131              :   {
     132            0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     133              :                                secname,
     134              :                                "UNIXPATH");
     135            0 :     GNUNET_free (secname);
     136            0 :     return NULL;
     137              :   }
     138              :   /* we use >= here because we want the sun_path to always
     139              :      be 0-terminated */
     140           27 :   if (strlen (unixpath) >= sizeof (esh->sa.sun_path))
     141              :   {
     142            0 :     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     143              :                                secname,
     144              :                                "UNIXPATH",
     145              :                                "path too long");
     146            0 :     GNUNET_free (unixpath);
     147            0 :     GNUNET_free (secname);
     148            0 :     return NULL;
     149              :   }
     150           27 :   GNUNET_free (secname);
     151           27 :   esh = GNUNET_new (struct TALER_CRYPTO_ExchangeSignHelper);
     152           27 :   esh->ekc = ekc;
     153           27 :   esh->ekc_cls = ekc_cls;
     154           27 :   esh->sa.sun_family = AF_UNIX;
     155           27 :   strncpy (esh->sa.sun_path,
     156              :            unixpath,
     157              :            sizeof (esh->sa.sun_path) - 1);
     158           27 :   GNUNET_free (unixpath);
     159           27 :   esh->sock = -1;
     160           27 :   if (GNUNET_OK !=
     161           27 :       try_connect (esh))
     162              :   {
     163            1 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     164              :                 "Could not connect to %s. Will keep trying\n",
     165              :                 "taler-exchange-helper-secmod-eddsa");
     166            1 :     return esh;
     167              :   }
     168           26 :   TALER_CRYPTO_helper_esign_poll (esh);
     169           26 :   return esh;
     170              : }
     171              : 
     172              : 
     173              : /**
     174              :  * Handle a #TALER_HELPER_EDDSA_MT_AVAIL message from the helper.
     175              :  *
     176              :  * @param esh helper context
     177              :  * @param hdr message that we received
     178              :  * @return #GNUNET_OK on success
     179              :  */
     180              : static enum GNUNET_GenericReturnValue
     181          102 : handle_mt_avail (struct TALER_CRYPTO_ExchangeSignHelper *esh,
     182              :                  const struct GNUNET_MessageHeader *hdr)
     183              : {
     184          102 :   const struct TALER_CRYPTO_EddsaKeyAvailableNotification *kan
     185              :     = (const struct TALER_CRYPTO_EddsaKeyAvailableNotification *) hdr;
     186              : 
     187          102 :   if (sizeof (*kan) != ntohs (hdr->size))
     188              :   {
     189            0 :     GNUNET_break_op (0);
     190            0 :     return GNUNET_SYSERR;
     191              :   }
     192          102 :   if (GNUNET_OK !=
     193          102 :       TALER_exchange_secmod_eddsa_verify (
     194              :         &kan->exchange_pub,
     195              :         GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
     196              :         GNUNET_TIME_relative_ntoh (kan->duration),
     197              :         &kan->secm_pub,
     198              :         &kan->secm_sig))
     199              :   {
     200            0 :     GNUNET_break_op (0);
     201            0 :     return GNUNET_SYSERR;
     202              :   }
     203          102 :   esh->ekc (esh->ekc_cls,
     204              :             GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
     205              :             GNUNET_TIME_relative_ntoh (kan->duration),
     206              :             &kan->exchange_pub,
     207              :             &kan->secm_pub,
     208              :             &kan->secm_sig);
     209          102 :   return GNUNET_OK;
     210              : }
     211              : 
     212              : 
     213              : /**
     214              :  * Handle a #TALER_HELPER_EDDSA_MT_PURGE message from the helper.
     215              :  *
     216              :  * @param esh helper context
     217              :  * @param hdr message that we received
     218              :  * @return #GNUNET_OK on success
     219              :  */
     220              : static enum GNUNET_GenericReturnValue
     221            3 : handle_mt_purge (struct TALER_CRYPTO_ExchangeSignHelper *esh,
     222              :                  const struct GNUNET_MessageHeader *hdr)
     223              : {
     224            3 :   const struct TALER_CRYPTO_EddsaKeyPurgeNotification *pn
     225              :     = (const struct TALER_CRYPTO_EddsaKeyPurgeNotification *) hdr;
     226              : 
     227            3 :   if (sizeof (*pn) != ntohs (hdr->size))
     228              :   {
     229            0 :     GNUNET_break_op (0);
     230            0 :     return GNUNET_SYSERR;
     231              :   }
     232            3 :   esh->ekc (esh->ekc_cls,
     233            3 :             GNUNET_TIME_UNIT_ZERO_TS,
     234            3 :             GNUNET_TIME_UNIT_ZERO,
     235              :             &pn->exchange_pub,
     236              :             NULL,
     237              :             NULL);
     238            3 :   return GNUNET_OK;
     239              : }
     240              : 
     241              : 
     242              : void
     243         1629 : TALER_CRYPTO_helper_esign_poll (struct TALER_CRYPTO_ExchangeSignHelper *esh)
     244              : {
     245              :   char buf[UINT16_MAX];
     246         1629 :   size_t off = 0;
     247         1629 :   unsigned int retry_limit = 3;
     248         1629 :   const struct GNUNET_MessageHeader *hdr
     249              :     = (const struct GNUNET_MessageHeader *) buf;
     250              : 
     251         1629 :   if (GNUNET_OK !=
     252         1629 :       try_connect (esh))
     253            0 :     return; /* give up */
     254              :   while (1)
     255           71 :   {
     256              :     uint16_t msize;
     257              :     ssize_t ret;
     258              : 
     259         1700 :     ret = recv (esh->sock,
     260              :                 buf + off,
     261              :                 sizeof (buf) - off,
     262         1700 :                 (esh->synced && (0 == off))
     263              :                 ? MSG_DONTWAIT
     264              :                 : 0);
     265         1700 :     if (ret < 0)
     266              :     {
     267         1629 :       if (EINTR == errno)
     268            0 :         continue;
     269         1629 :       if (EAGAIN == errno)
     270              :       {
     271         1629 :         GNUNET_assert (esh->synced);
     272         1629 :         GNUNET_assert (0 == off);
     273         1629 :         break;
     274              :       }
     275            0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     276              :                            "recv");
     277            0 :       do_disconnect (esh);
     278            0 :       if (0 == retry_limit)
     279            0 :         return; /* give up */
     280            0 :       if (GNUNET_OK !=
     281            0 :           try_connect (esh))
     282            0 :         return; /* give up */
     283            0 :       retry_limit--;
     284            0 :       continue;
     285              :     }
     286           71 :     if (0 == ret)
     287              :     {
     288            0 :       GNUNET_break (0 == off);
     289            0 :       return;
     290              :     }
     291           71 :     off += ret;
     292          202 : more:
     293          202 :     if (off < sizeof (struct GNUNET_MessageHeader))
     294           71 :       continue;
     295          131 :     msize = ntohs (hdr->size);
     296          131 :     if (msize < sizeof (struct GNUNET_MessageHeader))
     297              :     {
     298            0 :       GNUNET_break_op (0);
     299            0 :       do_disconnect (esh);
     300            0 :       return;
     301              :     }
     302          131 :     if (off < msize)
     303            0 :       continue;
     304          131 :     switch (ntohs (hdr->type))
     305              :     {
     306          102 :     case TALER_HELPER_EDDSA_MT_AVAIL:
     307          102 :       if (GNUNET_OK !=
     308          102 :           handle_mt_avail (esh,
     309              :                            hdr))
     310              :       {
     311            0 :         GNUNET_break_op (0);
     312            0 :         do_disconnect (esh);
     313            0 :         return;
     314              :       }
     315          102 :       break;
     316            3 :     case TALER_HELPER_EDDSA_MT_PURGE:
     317            3 :       if (GNUNET_OK !=
     318            3 :           handle_mt_purge (esh,
     319              :                            hdr))
     320              :       {
     321            0 :         GNUNET_break_op (0);
     322            0 :         do_disconnect (esh);
     323            0 :         return;
     324              :       }
     325            3 :       break;
     326           26 :     case TALER_HELPER_EDDSA_SYNCED:
     327           26 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     328              :                   "Now synchronized with EdDSA helper\n");
     329           26 :       esh->synced = true;
     330           26 :       break;
     331            0 :     default:
     332            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     333              :                   "Received unexpected message of type %d (len: %u)\n",
     334              :                   (unsigned int) ntohs (hdr->type),
     335              :                   (unsigned int) msize);
     336            0 :       GNUNET_break_op (0);
     337            0 :       do_disconnect (esh);
     338            0 :       return;
     339              :     }
     340          131 :     memmove (buf,
     341          131 :              &buf[msize],
     342              :              off - msize);
     343          131 :     off -= msize;
     344          131 :     goto more;
     345              :   }
     346              : }
     347              : 
     348              : 
     349              : enum TALER_ErrorCode
     350         1148 : TALER_CRYPTO_helper_esign_sign_ (
     351              :   struct TALER_CRYPTO_ExchangeSignHelper *esh,
     352              :   const struct GNUNET_CRYPTO_SignaturePurpose *purpose,
     353              :   struct TALER_ExchangePublicKeyP *exchange_pub,
     354              :   struct TALER_ExchangeSignatureP *exchange_sig)
     355              : {
     356         1148 :   uint32_t purpose_size = ntohl (purpose->size);
     357              : 
     358              :   /* clear the outputs, so that we never return
     359              :      uninitialized values on failures */
     360         1148 :   memset (exchange_pub,
     361              :           0,
     362              :           sizeof (*exchange_pub));
     363         1148 :   memset (exchange_sig,
     364              :           0,
     365              :           sizeof (*exchange_sig));
     366         1148 :   if (GNUNET_OK !=
     367         1148 :       try_connect (esh))
     368              :   {
     369            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     370              :                 "Failed to connect to helper\n");
     371            0 :     return TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE;
     372              :   }
     373         1148 :   GNUNET_assert (purpose_size >= sizeof (*purpose));
     374         1148 :   GNUNET_assert (purpose_size <
     375              :                  UINT16_MAX - sizeof (struct TALER_CRYPTO_EddsaSignRequest));
     376         1148 :   {
     377         1148 :     char buf[sizeof (struct TALER_CRYPTO_EddsaSignRequest) + purpose_size
     378         1148 :              - sizeof (struct GNUNET_CRYPTO_SignaturePurpose)];
     379         1148 :     struct TALER_CRYPTO_EddsaSignRequest *sr
     380              :       = (struct TALER_CRYPTO_EddsaSignRequest *) buf;
     381              : 
     382         1148 :     sr->header.size = htons (sizeof (buf));
     383         1148 :     sr->header.type = htons (TALER_HELPER_EDDSA_MT_REQ_SIGN);
     384         1148 :     sr->reserved = htonl (0);
     385         1148 :     GNUNET_memcpy (&sr->purpose,
     386              :                    purpose,
     387              :                    purpose_size);
     388         1148 :     if (GNUNET_OK !=
     389         1148 :         TALER_crypto_helper_send_all (esh->sock,
     390              :                                       buf,
     391              :                                       sizeof (buf)))
     392              :     {
     393            0 :       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
     394              :                                 "send",
     395              :                                 esh->sa.sun_path);
     396            0 :       do_disconnect (esh);
     397            0 :       return TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE;
     398              :     }
     399              :   }
     400              : 
     401              :   {
     402              :     char buf[UINT16_MAX];
     403         1148 :     size_t off = 0;
     404         1148 :     const struct GNUNET_MessageHeader *hdr
     405              :       = (const struct GNUNET_MessageHeader *) buf;
     406         1148 :     bool finished = false;
     407         1148 :     enum TALER_ErrorCode ec = TALER_EC_INVALID;
     408              : 
     409              :     while (1)
     410         1148 :     {
     411              :       ssize_t ret;
     412              :       uint16_t msize;
     413              : 
     414         3444 :       ret = recv (esh->sock,
     415         2296 :                   &buf[off],
     416              :                   sizeof (buf) - off,
     417         1148 :                   (finished && (0 == off))
     418              :                   ? MSG_DONTWAIT
     419              :                   : 0);
     420         2296 :       if (ret < 0)
     421              :       {
     422         1148 :         if (EINTR == errno)
     423            0 :           continue;
     424         1148 :         if (EAGAIN == errno)
     425              :         {
     426         1148 :           GNUNET_assert (finished);
     427         1148 :           GNUNET_assert (0 == off);
     428         1148 :           break;
     429              :         }
     430            0 :         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     431              :                              "recv");
     432            0 :         do_disconnect (esh);
     433            0 :         return TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE;
     434              :       }
     435         1148 :       if (0 == ret)
     436              :       {
     437              :         /* helper closed the connection */
     438            0 :         GNUNET_break (0 == off);
     439            0 :         do_disconnect (esh);
     440            0 :         if (! finished)
     441            0 :           return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     442            0 :         if (TALER_EC_NONE == ec)
     443            0 :           break;
     444            0 :         return ec;
     445              :       }
     446         1148 :       off += ret;
     447         2296 : more:
     448         2296 :       if (off < sizeof (struct GNUNET_MessageHeader))
     449         1148 :         continue;
     450         1148 :       msize = ntohs (hdr->size);
     451         1148 :       if (msize < sizeof (struct GNUNET_MessageHeader))
     452              :       {
     453            0 :         GNUNET_break_op (0);
     454            0 :         do_disconnect (esh);
     455            0 :         return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     456              :       }
     457         1148 :       if (off < msize)
     458            0 :         continue;
     459         1148 :       switch (ntohs (hdr->type))
     460              :       {
     461         1148 :       case TALER_HELPER_EDDSA_MT_RES_SIGNATURE:
     462         1148 :         if (msize != sizeof (struct TALER_CRYPTO_EddsaSignResponse))
     463              :         {
     464            0 :           GNUNET_break_op (0);
     465            0 :           do_disconnect (esh);
     466            0 :           return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     467              :         }
     468         1148 :         if (finished)
     469              :         {
     470            0 :           GNUNET_break_op (0);
     471            0 :           do_disconnect (esh);
     472            0 :           return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     473              :         }
     474              :         {
     475         1148 :           const struct TALER_CRYPTO_EddsaSignResponse *sr =
     476              :             (const struct TALER_CRYPTO_EddsaSignResponse *) buf;
     477         1148 :           *exchange_sig = sr->exchange_sig;
     478         1148 :           *exchange_pub = sr->exchange_pub;
     479         1148 :           finished = true;
     480         1148 :           ec = TALER_EC_NONE;
     481         1148 :           break;
     482              :         }
     483            0 :       case TALER_HELPER_EDDSA_MT_RES_SIGN_FAILURE:
     484            0 :         if (msize != sizeof (struct TALER_CRYPTO_EddsaSignFailure))
     485              :         {
     486            0 :           GNUNET_break_op (0);
     487            0 :           do_disconnect (esh);
     488            0 :           return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     489              :         }
     490              :         {
     491            0 :           const struct TALER_CRYPTO_EddsaSignFailure *sf =
     492              :             (const struct TALER_CRYPTO_EddsaSignFailure *) buf;
     493              : 
     494            0 :           finished = true;
     495            0 :           ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
     496            0 :           break;
     497              :         }
     498            0 :       case TALER_HELPER_EDDSA_MT_AVAIL:
     499            0 :         if (GNUNET_OK !=
     500            0 :             handle_mt_avail (esh,
     501              :                              hdr))
     502              :         {
     503            0 :           GNUNET_break_op (0);
     504            0 :           do_disconnect (esh);
     505            0 :           return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     506              :         }
     507            0 :         break; /* while(1) loop ensures we recv() again */
     508            0 :       case TALER_HELPER_EDDSA_MT_PURGE:
     509            0 :         if (GNUNET_OK !=
     510            0 :             handle_mt_purge (esh,
     511              :                              hdr))
     512              :         {
     513            0 :           GNUNET_break_op (0);
     514            0 :           do_disconnect (esh);
     515            0 :           return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     516              :         }
     517            0 :         break; /* while(1) loop ensures we recv() again */
     518            0 :       case TALER_HELPER_EDDSA_SYNCED:
     519            0 :         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     520              :                     "Synchronized add odd time with EdDSA helper!\n");
     521            0 :         esh->synced = true;
     522            0 :         break;
     523            0 :       default:
     524            0 :         GNUNET_break_op (0);
     525            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     526              :                     "Received unexpected message of type %u\n",
     527              :                     ntohs (hdr->type));
     528            0 :         do_disconnect (esh);
     529            0 :         return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     530              :       }
     531         1148 :       memmove (buf,
     532         1148 :                &buf[msize],
     533              :                off - msize);
     534         1148 :       off -= msize;
     535         1148 :       goto more;
     536              :     } /* while(1) */
     537         1148 :     return ec;
     538              :   }
     539              : }
     540              : 
     541              : 
     542              : void
     543            3 : TALER_CRYPTO_helper_esign_revoke (
     544              :   struct TALER_CRYPTO_ExchangeSignHelper *esh,
     545              :   const struct TALER_ExchangePublicKeyP *exchange_pub)
     546              : {
     547            3 :   if (GNUNET_OK !=
     548            3 :       try_connect (esh))
     549            0 :     return; /* give up */
     550              :   {
     551            3 :     struct TALER_CRYPTO_EddsaRevokeRequest rr = {
     552            3 :       .header.size = htons (sizeof (rr)),
     553            3 :       .header.type = htons (TALER_HELPER_EDDSA_MT_REQ_REVOKE),
     554              :       .exchange_pub = *exchange_pub
     555              :     };
     556              : 
     557            3 :     if (GNUNET_OK !=
     558            3 :         TALER_crypto_helper_send_all (esh->sock,
     559              :                                       &rr,
     560              :                                       sizeof (rr)))
     561              :     {
     562            0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     563              :                            "send");
     564            0 :       do_disconnect (esh);
     565            0 :       return;
     566              :     }
     567              :   }
     568              : }
     569              : 
     570              : 
     571              : void
     572           27 : TALER_CRYPTO_helper_esign_disconnect (
     573              :   struct TALER_CRYPTO_ExchangeSignHelper *esh)
     574              : {
     575           27 :   if (-1 != esh->sock)
     576           26 :     do_disconnect (esh);
     577           27 :   GNUNET_free (esh);
     578           27 : }
     579              : 
     580              : 
     581              : /* end of crypto_helper_esign.c */
        

Generated by: LCOV version 2.0-1