LCOV - code coverage report
Current view: top level - util - crypto_helper_denom.c (source / functions) Hit Total Coverage
Test: GNU Taler exchange coverage report Lines: 190 303 62.7 %
Date: 2021-08-30 06:43:37 Functions: 10 10 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   This file is part of TALER
       3             :   Copyright (C) 2020 Taler Systems SA
       4             : 
       5             :   TALER is free software; you can redistribute it and/or modify it under the
       6             :   terms of the GNU General Public License as published by the Free Software
       7             :   Foundation; either version 3, or (at your option) any later version.
       8             : 
       9             :   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
      10             :   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
      11             :   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
      12             : 
      13             :   You should have received a copy of the GNU General Public License along with
      14             :   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
      15             : */
      16             : /**
      17             :  * @file util/crypto_helper_denom.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_util.h"
      23             : #include "taler_signatures.h"
      24             : #include "taler-exchange-secmod-rsa.h"
      25             : #include <poll.h>
      26             : 
      27             : 
      28             : struct TALER_CRYPTO_DenominationHelper
      29             : {
      30             :   /**
      31             :    * Function to call with updates to available key material.
      32             :    */
      33             :   TALER_CRYPTO_DenominationKeyStatusCallback dkc;
      34             : 
      35             :   /**
      36             :    * Closure for @e dkc
      37             :    */
      38             :   void *dkc_cls;
      39             : 
      40             :   /**
      41             :    * Socket address of the denomination helper process.
      42             :    * Used to reconnect if the connection breaks.
      43             :    */
      44             :   struct sockaddr_un sa;
      45             : 
      46             :   /**
      47             :    * Socket address of this process.
      48             :    */
      49             :   struct sockaddr_un my_sa;
      50             : 
      51             :   /**
      52             :    * Template for @e my_sa.
      53             :    */
      54             :   char *template;
      55             : 
      56             :   /**
      57             :    * The UNIX domain socket, -1 if we are currently not connected.
      58             :    */
      59             :   int sock;
      60             : 
      61             :   /**
      62             :    * Have we ever been sync'ed?
      63             :    */
      64             :   bool synced;
      65             : };
      66             : 
      67             : 
      68             : /**
      69             :  * Disconnect from the helper process.  Updates
      70             :  * @e sock field in @a dh.
      71             :  *
      72             :  * @param[in,out] dh handle to tear down connection of
      73             :  */
      74             : static void
      75          40 : do_disconnect (struct TALER_CRYPTO_DenominationHelper *dh)
      76             : {
      77          40 :   GNUNET_break (0 == close (dh->sock));
      78          40 :   if (0 != unlink (dh->my_sa.sun_path))
      79           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
      80             :                               "unlink",
      81             :                               dh->my_sa.sun_path);
      82          40 :   dh->sock = -1;
      83          40 : }
      84             : 
      85             : 
      86             : /**
      87             :  * Try to connect to the helper process.  Updates
      88             :  * @e sock field in @a dh.
      89             :  *
      90             :  * @param[in,out] dh handle to establish connection for
      91             :  */
      92             : static void
      93         548 : try_connect (struct TALER_CRYPTO_DenominationHelper *dh)
      94             : {
      95             :   char *tmpdir;
      96             : 
      97         548 :   if (-1 != dh->sock)
      98         508 :     return;
      99          40 :   dh->sock = socket (AF_UNIX,
     100             :                      SOCK_DGRAM,
     101             :                      0);
     102          40 :   if (-1 == dh->sock)
     103             :   {
     104           0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     105             :                          "socket");
     106           0 :     return;
     107             :   }
     108          40 :   tmpdir = GNUNET_DISK_mktemp (dh->template);
     109          40 :   if (NULL == tmpdir)
     110             :   {
     111           0 :     do_disconnect (dh);
     112           0 :     return;
     113             :   }
     114             :   /* we use >= here because we want the sun_path to always
     115             :      be 0-terminated */
     116          40 :   if (strlen (tmpdir) >= sizeof (dh->sa.sun_path))
     117             :   {
     118           0 :     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     119             :                                "PATHS",
     120             :                                "TALER_RUNTIME_DIR",
     121             :                                "path too long");
     122           0 :     GNUNET_free (tmpdir);
     123           0 :     do_disconnect (dh);
     124           0 :     return;
     125             :   }
     126          40 :   dh->my_sa.sun_family = AF_UNIX;
     127          40 :   strncpy (dh->my_sa.sun_path,
     128             :            tmpdir,
     129             :            sizeof (dh->sa.sun_path) - 1);
     130          40 :   if (0 != unlink (tmpdir))
     131           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
     132             :                               "unlink",
     133             :                               tmpdir);
     134          40 :   if (0 != bind (dh->sock,
     135          40 :                  (const struct sockaddr *) &dh->my_sa,
     136             :                  sizeof (dh->my_sa)))
     137             :   {
     138           0 :     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
     139             :                               "bind",
     140             :                               tmpdir);
     141           0 :     do_disconnect (dh);
     142           0 :     GNUNET_free (tmpdir);
     143           0 :     return;
     144             :   }
     145             :   /* Fix permissions on client UNIX domain socket,
     146             :      just in case umask() is not set to enable group write */
     147             :   {
     148             :     char path[sizeof (dh->my_sa.sun_path) + 1];
     149             : 
     150          40 :     strncpy (path,
     151          40 :              dh->my_sa.sun_path,
     152             :              sizeof (path) - 1);
     153          40 :     path[sizeof (dh->my_sa.sun_path)] = '\0';
     154             : 
     155          40 :     if (0 != chmod (path,
     156             :                     S_IRUSR | S_IWUSR | S_IWGRP))
     157             :     {
     158           0 :       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
     159             :                                 "chmod",
     160             :                                 path);
     161             :     }
     162             :   }
     163          40 :   GNUNET_free (tmpdir);
     164             :   {
     165          40 :     struct GNUNET_MessageHeader hdr = {
     166          40 :       .size = htons (sizeof (hdr)),
     167          40 :       .type = htons (TALER_HELPER_RSA_MT_REQ_INIT)
     168             :     };
     169             :     ssize_t ret;
     170             : 
     171          40 :     ret = sendto (dh->sock,
     172             :                   &hdr,
     173             :                   sizeof (hdr),
     174             :                   0,
     175          40 :                   (const struct sockaddr *) &dh->sa,
     176             :                   sizeof (dh->sa));
     177          40 :     if (ret < 0)
     178             :     {
     179           2 :       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
     180             :                                 "sendto",
     181             :                                 dh->sa.sun_path);
     182           2 :       do_disconnect (dh);
     183           2 :       return;
     184             :     }
     185             :     /* We are using SOCK_DGRAM, partial writes should not be possible */
     186          38 :     GNUNET_break (((size_t) ret) == sizeof (hdr));
     187          38 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     188             :                 "Successfully sent REQ_INIT\n");
     189             :   }
     190             : 
     191             : }
     192             : 
     193             : 
     194             : struct TALER_CRYPTO_DenominationHelper *
     195          43 : TALER_CRYPTO_helper_denom_connect (
     196             :   const struct GNUNET_CONFIGURATION_Handle *cfg,
     197             :   TALER_CRYPTO_DenominationKeyStatusCallback dkc,
     198             :   void *dkc_cls)
     199             : {
     200             :   struct TALER_CRYPTO_DenominationHelper *dh;
     201             :   char *unixpath;
     202             : 
     203          43 :   if (GNUNET_OK !=
     204          43 :       GNUNET_CONFIGURATION_get_value_filename (cfg,
     205             :                                                "taler-exchange-secmod-rsa",
     206             :                                                "UNIXPATH",
     207             :                                                &unixpath))
     208             :   {
     209           0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     210             :                                "taler-exchange-secmod-rsa",
     211             :                                "UNIXPATH");
     212           0 :     return NULL;
     213             :   }
     214             :   /* we use >= here because we want the sun_path to always
     215             :      be 0-terminated */
     216          43 :   if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
     217             :   {
     218           0 :     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     219             :                                "taler-exchange-secmod-rsa",
     220             :                                "UNIXPATH",
     221             :                                "path too long");
     222           0 :     GNUNET_free (unixpath);
     223           0 :     return NULL;
     224             :   }
     225          43 :   dh = GNUNET_new (struct TALER_CRYPTO_DenominationHelper);
     226          43 :   dh->dkc = dkc;
     227          43 :   dh->dkc_cls = dkc_cls;
     228          43 :   dh->sa.sun_family = AF_UNIX;
     229          43 :   strncpy (dh->sa.sun_path,
     230             :            unixpath,
     231             :            sizeof (dh->sa.sun_path) - 1);
     232          43 :   GNUNET_free (unixpath);
     233          43 :   dh->sock = -1;
     234             :   {
     235             :     char *tmpdir;
     236             :     char *template;
     237             : 
     238          43 :     if (GNUNET_OK !=
     239          43 :         GNUNET_CONFIGURATION_get_value_filename (cfg,
     240             :                                                  "taler-exchange-secmod-rsa",
     241             :                                                  "CLIENT_DIR",
     242             :                                                  &tmpdir))
     243             :     {
     244           0 :       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     245             :                                  "taler-exchange-secmod-rsa",
     246             :                                  "CLIENT_DIR");
     247           6 :       return NULL;
     248             :     }
     249          43 :     GNUNET_asprintf (&template,
     250             :                      "%s/cli",
     251             :                      tmpdir);
     252             :     /* We expect the service to create the client directory */
     253          43 :     if (GNUNET_OK !=
     254          43 :         GNUNET_DISK_directory_test (tmpdir,
     255             :                                     GNUNET_YES))
     256             :     {
     257           6 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     258             :                   "Unable to read secmod client directory (%s)\n",
     259             :                   tmpdir);
     260           6 :       GNUNET_free (dh);
     261           6 :       GNUNET_free (template);
     262           6 :       GNUNET_free (tmpdir);
     263           6 :       return NULL;
     264             :     }
     265          37 :     GNUNET_free (tmpdir);
     266          37 :     dh->template = template;
     267          37 :     if (strlen (template) >= sizeof (dh->sa.sun_path))
     268             :     {
     269           0 :       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     270             :                                  "PATHS",
     271             :                                  "TALER_RUNTIME_DIR",
     272             :                                  "path too long");
     273           0 :       TALER_CRYPTO_helper_denom_disconnect (dh);
     274           0 :       return NULL;
     275             :     }
     276             :   }
     277          37 :   TALER_CRYPTO_helper_denom_poll (dh);
     278          37 :   return dh;
     279             : }
     280             : 
     281             : 
     282             : /**
     283             :  * Handle a #TALER_HELPER_RSA_MT_AVAIL message from the helper.
     284             :  *
     285             :  * @param dh helper context
     286             :  * @param hdr message that we received
     287             :  * @return #GNUNET_OK on success
     288             :  */
     289             : static int
     290         513 : handle_mt_avail (struct TALER_CRYPTO_DenominationHelper *dh,
     291             :                  const struct GNUNET_MessageHeader *hdr)
     292             : {
     293         513 :   const struct TALER_CRYPTO_RsaKeyAvailableNotification *kan
     294             :     = (const struct TALER_CRYPTO_RsaKeyAvailableNotification *) hdr;
     295         513 :   const char *buf = (const char *) &kan[1];
     296             :   const char *section_name;
     297             : 
     298         513 :   if (sizeof (*kan) > ntohs (hdr->size))
     299             :   {
     300           0 :     GNUNET_break_op (0);
     301           0 :     return GNUNET_SYSERR;
     302             :   }
     303         513 :   if (ntohs (hdr->size) !=
     304             :       sizeof (*kan)
     305         513 :       + ntohs (kan->pub_size)
     306         513 :       + ntohs (kan->section_name_len))
     307             :   {
     308           0 :     GNUNET_break_op (0);
     309           0 :     return GNUNET_SYSERR;
     310             :   }
     311         513 :   section_name = &buf[ntohs (kan->pub_size)];
     312         513 :   if ('\0' != section_name[ntohs (kan->section_name_len) - 1])
     313             :   {
     314           0 :     GNUNET_break_op (0);
     315           0 :     return GNUNET_SYSERR;
     316             :   }
     317             : 
     318             :   {
     319             :     struct TALER_DenominationPublicKey denom_pub;
     320             :     struct GNUNET_HashCode h_denom_pub;
     321             : 
     322             :     denom_pub.rsa_public_key
     323        1026 :       = GNUNET_CRYPTO_rsa_public_key_decode (buf,
     324         513 :                                              ntohs (kan->pub_size));
     325         513 :     if (NULL == denom_pub.rsa_public_key)
     326             :     {
     327           0 :       GNUNET_break_op (0);
     328           0 :       return GNUNET_SYSERR;
     329             :     }
     330         513 :     GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key,
     331             :                                        &h_denom_pub);
     332         513 :     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     333             :                 "Received RSA key %s (%s)\n",
     334             :                 GNUNET_h2s (&h_denom_pub),
     335             :                 section_name);
     336         513 :     if (GNUNET_OK !=
     337         513 :         TALER_exchange_secmod_rsa_verify (
     338             :           &h_denom_pub,
     339             :           section_name,
     340             :           GNUNET_TIME_absolute_ntoh (kan->anchor_time),
     341             :           GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
     342             :           &kan->secm_pub,
     343             :           &kan->secm_sig))
     344             :     {
     345           0 :       GNUNET_break_op (0);
     346           0 :       GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
     347           0 :       return GNUNET_SYSERR;
     348             :     }
     349         513 :     dh->dkc (dh->dkc_cls,
     350             :              section_name,
     351             :              GNUNET_TIME_absolute_ntoh (kan->anchor_time),
     352             :              GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
     353             :              &h_denom_pub,
     354             :              &denom_pub,
     355             :              &kan->secm_pub,
     356             :              &kan->secm_sig);
     357         513 :     GNUNET_CRYPTO_rsa_public_key_free (denom_pub.rsa_public_key);
     358             :   }
     359         513 :   return GNUNET_OK;
     360             : }
     361             : 
     362             : 
     363             : /**
     364             :  * Handle a #TALER_HELPER_RSA_MT_PURGE message from the helper.
     365             :  *
     366             :  * @param dh helper context
     367             :  * @param hdr message that we received
     368             :  * @return #GNUNET_OK on success
     369             :  */
     370             : static int
     371          10 : handle_mt_purge (struct TALER_CRYPTO_DenominationHelper *dh,
     372             :                  const struct GNUNET_MessageHeader *hdr)
     373             : {
     374          10 :   const struct TALER_CRYPTO_RsaKeyPurgeNotification *pn
     375             :     = (const struct TALER_CRYPTO_RsaKeyPurgeNotification *) hdr;
     376             : 
     377          10 :   if (sizeof (*pn) != ntohs (hdr->size))
     378             :   {
     379           0 :     GNUNET_break_op (0);
     380           0 :     return GNUNET_SYSERR;
     381             :   }
     382          10 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     383             :               "Received revocation of denomination key %s\n",
     384             :               GNUNET_h2s (&pn->h_denom_pub));
     385          10 :   dh->dkc (dh->dkc_cls,
     386             :            NULL,
     387             :            GNUNET_TIME_UNIT_ZERO_ABS,
     388             :            GNUNET_TIME_UNIT_ZERO,
     389             :            &pn->h_denom_pub,
     390             :            NULL,
     391             :            NULL,
     392             :            NULL);
     393          10 :   return GNUNET_OK;
     394             : }
     395             : 
     396             : 
     397             : /**
     398             :  * Wait until the socket is ready to read.
     399             :  *
     400             :  * @param dh helper to wait for
     401             :  * @return false on timeout (after 1s)
     402             :  */
     403             : static bool
     404         112 : await_read_ready (struct TALER_CRYPTO_DenominationHelper *dh)
     405             : {
     406             :   /* wait for reply with 1s timeout */
     407         112 :   struct pollfd pfd = {
     408         112 :     .fd = dh->sock,
     409             :     .events = POLLIN
     410             :   };
     411             :   sigset_t sigmask;
     412         112 :   struct timespec ts = {
     413             :     .tv_sec = 1
     414             :   };
     415             :   int ret;
     416             : 
     417         112 :   GNUNET_assert (0 == sigemptyset (&sigmask));
     418         112 :   GNUNET_assert (0 == sigaddset (&sigmask, SIGTERM));
     419         112 :   GNUNET_assert (0 == sigaddset (&sigmask, SIGHUP));
     420         112 :   ret = ppoll (&pfd,
     421             :                1,
     422             :                &ts,
     423             :                &sigmask);
     424         112 :   if ( (-1 == ret) &&
     425           0 :        (EINTR != errno) )
     426           0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
     427             :                          "ppoll");
     428         112 :   return (0 < ret);
     429             : }
     430             : 
     431             : 
     432             : void
     433         463 : TALER_CRYPTO_helper_denom_poll (struct TALER_CRYPTO_DenominationHelper *dh)
     434             : {
     435             :   char buf[UINT16_MAX];
     436             :   ssize_t ret;
     437         463 :   unsigned int retry_limit = 3;
     438         463 :   const struct GNUNET_MessageHeader *hdr
     439             :     = (const struct GNUNET_MessageHeader *) buf;
     440         463 :   int flag = MSG_DONTWAIT;
     441             : 
     442         463 :   try_connect (dh);
     443         463 :   if (-1 == dh->sock)
     444           2 :     return; /* give up */
     445             :   while (1)
     446             :   {
     447        1060 :     ret = recv (dh->sock,
     448             :                 buf,
     449             :                 sizeof (buf),
     450             :                 flag);
     451        1060 :     if (ret < 0)
     452             :     {
     453         500 :       if (EAGAIN == errno)
     454             :       {
     455             :         /* EAGAIN should only happen if we did not
     456             :            already go through this loop */
     457         500 :         GNUNET_assert (0 != flag);
     458         500 :         if (dh->synced)
     459         461 :           break;
     460          39 :         if (! await_read_ready (dh))
     461             :         {
     462             :           /* timeout AND not synced => full reconnect */
     463           1 :           GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     464             :                       "Restarting connection to RSA helper, did not come up properly\n");
     465           1 :           do_disconnect (dh);
     466           1 :           if (0 == retry_limit)
     467           0 :             return; /* give up */
     468           1 :           try_connect (dh);
     469           1 :           if (-1 == dh->sock)
     470           0 :             return; /* give up */
     471           1 :           retry_limit--;
     472           1 :           flag = MSG_DONTWAIT;
     473             :         }
     474             :         else
     475             :         {
     476          38 :           flag = 0; /* syscall must be non-blocking this time */
     477             :         }
     478          39 :         continue; /* try again */
     479             :       }
     480           0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     481             :                            "recv");
     482           0 :       do_disconnect (dh);
     483           0 :       return;
     484             :     }
     485         560 :     retry_limit = 10;
     486         560 :     flag = MSG_DONTWAIT;
     487         560 :     if ( (ret < sizeof (struct GNUNET_MessageHeader)) ||
     488         560 :          (ret != ntohs (hdr->size)) )
     489             :     {
     490           0 :       GNUNET_break_op (0);
     491           0 :       do_disconnect (dh);
     492           0 :       return;
     493             :     }
     494         560 :     switch (ntohs (hdr->type))
     495             :     {
     496         513 :     case TALER_HELPER_RSA_MT_AVAIL:
     497         513 :       if (GNUNET_OK !=
     498         513 :           handle_mt_avail (dh,
     499             :                            hdr))
     500             :       {
     501           0 :         GNUNET_break_op (0);
     502           0 :         do_disconnect (dh);
     503           0 :         return;
     504             :       }
     505         513 :       break;
     506          10 :     case TALER_HELPER_RSA_MT_PURGE:
     507          10 :       if (GNUNET_OK !=
     508          10 :           handle_mt_purge (dh,
     509             :                            hdr))
     510             :       {
     511           0 :         GNUNET_break_op (0);
     512           0 :         do_disconnect (dh);
     513           0 :         return;
     514             :       }
     515          10 :       break;
     516          37 :     case TALER_HELPER_RSA_SYNCED:
     517          37 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     518             :                   "Now synchronized with RSA helper\n");
     519          37 :       dh->synced = true;
     520          37 :       break;
     521           0 :     default:
     522           0 :       GNUNET_break_op (0);
     523           0 :       do_disconnect (dh);
     524           0 :       return;
     525             :     }
     526             :   }
     527             : }
     528             : 
     529             : 
     530             : struct TALER_DenominationSignature
     531          73 : TALER_CRYPTO_helper_denom_sign (
     532             :   struct TALER_CRYPTO_DenominationHelper *dh,
     533             :   const struct GNUNET_HashCode *h_denom_pub,
     534             :   const void *msg,
     535             :   size_t msg_size,
     536             :   enum TALER_ErrorCode *ec)
     537             : {
     538          73 :   struct TALER_DenominationSignature ds = { NULL };
     539          73 :   {
     540          73 :     char buf[sizeof (struct TALER_CRYPTO_SignRequest) + msg_size];
     541          73 :     struct TALER_CRYPTO_SignRequest *sr
     542             :       = (struct TALER_CRYPTO_SignRequest *) buf;
     543             :     ssize_t ret;
     544             : 
     545          73 :     try_connect (dh);
     546          73 :     if (-1 == dh->sock)
     547             :     {
     548           0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     549             :                   "Failed to connect to helper\n");
     550           0 :       *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     551           0 :       return ds;
     552             :     }
     553          73 :     sr->header.size = htons (sizeof (buf));
     554          73 :     sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
     555          73 :     sr->reserved = htonl (0);
     556          73 :     sr->h_denom_pub = *h_denom_pub;
     557          73 :     memcpy (&sr[1],
     558             :             msg,
     559             :             msg_size);
     560          73 :     ret = sendto (dh->sock,
     561             :                   buf,
     562             :                   sizeof (buf),
     563             :                   0,
     564          73 :                   (const struct sockaddr *) &dh->sa,
     565             :                   sizeof (dh->sa));
     566          73 :     if (ret < 0)
     567             :     {
     568           0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     569             :                            "sendto");
     570           0 :       do_disconnect (dh);
     571           0 :       *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     572           0 :       return ds;
     573             :     }
     574             :     /* We are using SOCK_DGRAM, partial writes should not be possible */
     575          73 :     GNUNET_break (((size_t) ret) == sizeof (buf));
     576             :   }
     577             : 
     578             :   while (1)
     579           0 :   {
     580             :     char buf[UINT16_MAX];
     581             :     ssize_t ret;
     582          73 :     const struct GNUNET_MessageHeader *hdr
     583             :       = (const struct GNUNET_MessageHeader *) buf;
     584             : 
     585          73 :     if (! await_read_ready (dh))
     586             :     {
     587           0 :       do_disconnect (dh);
     588           0 :       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     589             :                   "Timeout waiting for helper\n");
     590           0 :       *ec = TALER_EC_GENERIC_TIMEOUT;
     591          73 :       return ds;
     592             :     }
     593          73 :     ret = recv (dh->sock,
     594             :                 buf,
     595             :                 sizeof (buf),
     596             :                 0);
     597          73 :     if (ret < 0)
     598             :     {
     599           0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     600             :                            "recv");
     601           0 :       do_disconnect (dh);
     602           0 :       *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     603           0 :       return ds;
     604             :     }
     605          73 :     if ( (ret < sizeof (struct GNUNET_MessageHeader)) ||
     606          73 :          (ret != ntohs (hdr->size)) )
     607             :     {
     608           0 :       GNUNET_break_op (0);
     609           0 :       do_disconnect (dh);
     610           0 :       *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     611           0 :       return ds;
     612             :     }
     613          73 :     switch (ntohs (hdr->type))
     614             :     {
     615          67 :     case TALER_HELPER_RSA_MT_RES_SIGNATURE:
     616          67 :       if (ret < sizeof (struct TALER_CRYPTO_SignResponse))
     617             :       {
     618           0 :         GNUNET_break_op (0);
     619           0 :         do_disconnect (dh);
     620           0 :         *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     621           0 :         return ds;
     622             :       }
     623             :       {
     624          67 :         const struct TALER_CRYPTO_SignResponse *sr =
     625             :           (const struct TALER_CRYPTO_SignResponse *) buf;
     626             :         struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
     627             : 
     628          67 :         rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (&sr[1],
     629             :                                                             ret - sizeof (*sr));
     630          67 :         if (NULL == rsa_signature)
     631             :         {
     632           0 :           GNUNET_break_op (0);
     633           0 :           do_disconnect (dh);
     634           0 :           *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     635           0 :           return ds;
     636             :         }
     637          67 :         *ec = TALER_EC_NONE;
     638          67 :         ds.rsa_signature = rsa_signature;
     639          67 :         return ds;
     640             :       }
     641           6 :     case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
     642           6 :       if (ret != sizeof (struct TALER_CRYPTO_SignFailure))
     643             :       {
     644           0 :         GNUNET_break_op (0);
     645           0 :         do_disconnect (dh);
     646           0 :         *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     647           0 :         return ds;
     648             :       }
     649             :       {
     650           6 :         const struct TALER_CRYPTO_SignFailure *sf =
     651             :           (const struct TALER_CRYPTO_SignFailure *) buf;
     652             : 
     653           6 :         *ec = (enum TALER_ErrorCode) ntohl (sf->ec);
     654           6 :         return ds;
     655             :       }
     656           0 :     case TALER_HELPER_RSA_MT_AVAIL:
     657           0 :       if (GNUNET_OK !=
     658           0 :           handle_mt_avail (dh,
     659             :                            hdr))
     660             :       {
     661           0 :         GNUNET_break_op (0);
     662           0 :         do_disconnect (dh);
     663           0 :         *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     664           0 :         return ds;
     665             :       }
     666           0 :       break; /* while(1) loop ensures we recvfrom() again */
     667           0 :     case TALER_HELPER_RSA_MT_PURGE:
     668           0 :       if (GNUNET_OK !=
     669           0 :           handle_mt_purge (dh,
     670             :                            hdr))
     671             :       {
     672           0 :         GNUNET_break_op (0);
     673           0 :         do_disconnect (dh);
     674           0 :         *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     675           0 :         return ds;
     676             :       }
     677           0 :       break; /* while(1) loop ensures we recvfrom() again */
     678           0 :     default:
     679           0 :       GNUNET_break_op (0);
     680           0 :       do_disconnect (dh);
     681           0 :       *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     682           0 :       return ds;
     683             :     }
     684             :   }
     685             : }
     686             : 
     687             : 
     688             : void
     689          11 : TALER_CRYPTO_helper_denom_revoke (
     690             :   struct TALER_CRYPTO_DenominationHelper *dh,
     691             :   const struct GNUNET_HashCode *h_denom_pub)
     692             : {
     693          11 :   struct TALER_CRYPTO_RevokeRequest rr = {
     694          11 :     .header.size = htons (sizeof (rr)),
     695          11 :     .header.type = htons (TALER_HELPER_RSA_MT_REQ_REVOKE),
     696             :     .h_denom_pub = *h_denom_pub
     697             :   };
     698             :   ssize_t ret;
     699             : 
     700          11 :   try_connect (dh);
     701          11 :   if (-1 == dh->sock)
     702           0 :     return; /* give up */
     703          11 :   ret = sendto (dh->sock,
     704             :                 &rr,
     705             :                 sizeof (rr),
     706             :                 0,
     707          11 :                 (const struct sockaddr *) &dh->sa,
     708             :                 sizeof (dh->sa));
     709          11 :   if (ret < 0)
     710             :   {
     711           0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     712             :                          "sendto");
     713           0 :     do_disconnect (dh);
     714           0 :     return;
     715             :   }
     716             :   /* We are using SOCK_DGRAM, partial writes should not be possible */
     717          11 :   GNUNET_break (((size_t) ret) == sizeof (rr));
     718          11 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     719             :               "Requested revocation of denomination key %s\n",
     720             :               GNUNET_h2s (h_denom_pub));
     721             : }
     722             : 
     723             : 
     724             : void
     725          37 : TALER_CRYPTO_helper_denom_disconnect (
     726             :   struct TALER_CRYPTO_DenominationHelper *dh)
     727             : {
     728          37 :   if (-1 != dh->sock)
     729          37 :     do_disconnect (dh);
     730          37 :   GNUNET_free (dh->template);
     731          37 :   GNUNET_free (dh);
     732          37 : }
     733             : 
     734             : 
     735             : /* end of crypto_helper_denom.c */

Generated by: LCOV version 1.14