LCOV - code coverage report
Current view: top level - util - crypto_helper_rsa.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 62.6 % 454 284
Test Date: 2026-01-04 22:17:00 Functions: 100.0 % 10 10

            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_rsa.c
      18              :  * @brief utility functions for running out-of-process private key operations
      19              :  * @author Christian Grothoff
      20              :  */
      21              : #include "taler/platform.h"
      22              : #include "taler/taler_util.h"
      23              : #include "taler/taler_signatures.h"
      24              : #include "crypto_helper_common.h"
      25              : #include "secmod_rsa.h"
      26              : #include <poll.h>
      27              : 
      28              : 
      29              : struct TALER_CRYPTO_RsaDenominationHelper
      30              : {
      31              :   /**
      32              :    * Function to call with updates to available key material.
      33              :    */
      34              :   TALER_CRYPTO_RsaDenominationKeyStatusCallback 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_RsaDenominationHelper *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         1844 : try_connect (struct TALER_CRYPTO_RsaDenominationHelper *dh)
      83              : {
      84         1844 :   if (-1 != dh->sock)
      85         1817 :     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_rsa_poll (dh);
     109           26 :   return GNUNET_OK;
     110              : }
     111              : 
     112              : 
     113              : struct TALER_CRYPTO_RsaDenominationHelper *
     114           27 : TALER_CRYPTO_helper_rsa_connect (
     115              :   const struct GNUNET_CONFIGURATION_Handle *cfg,
     116              :   const char *section,
     117              :   TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc,
     118              :   void *dkc_cls)
     119              : {
     120              :   struct TALER_CRYPTO_RsaDenominationHelper *dh;
     121              :   char *unixpath;
     122              :   char *secname;
     123              : 
     124           27 :   GNUNET_asprintf (&secname,
     125              :                    "%s-secmod-rsa",
     126              :                    section);
     127              : 
     128           27 :   if (GNUNET_OK !=
     129           27 :       GNUNET_CONFIGURATION_get_value_filename (cfg,
     130              :                                                secname,
     131              :                                                "UNIXPATH",
     132              :                                                &unixpath))
     133              :   {
     134            0 :     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
     135              :                                secname,
     136              :                                "UNIXPATH");
     137            0 :     GNUNET_free (secname);
     138            0 :     return NULL;
     139              :   }
     140              :   /* we use >= here because we want the sun_path to always
     141              :      be 0-terminated */
     142           27 :   if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
     143              :   {
     144            0 :     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
     145              :                                secname,
     146              :                                "UNIXPATH",
     147              :                                "path too long");
     148            0 :     GNUNET_free (unixpath);
     149            0 :     GNUNET_free (secname);
     150            0 :     return NULL;
     151              :   }
     152           27 :   GNUNET_free (secname);
     153           27 :   dh = GNUNET_new (struct TALER_CRYPTO_RsaDenominationHelper);
     154           27 :   dh->dkc = dkc;
     155           27 :   dh->dkc_cls = dkc_cls;
     156           27 :   dh->sa.sun_family = AF_UNIX;
     157           27 :   strncpy (dh->sa.sun_path,
     158              :            unixpath,
     159              :            sizeof (dh->sa.sun_path) - 1);
     160           27 :   GNUNET_free (unixpath);
     161           27 :   dh->sock = -1;
     162           27 :   if (GNUNET_OK !=
     163           27 :       try_connect (dh))
     164              :   {
     165            1 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     166              :                 "Could not connect to %s. Will keep trying\n",
     167              :                 "taler-exchange-helper-secmod-rsa");
     168              :   }
     169           27 :   return dh;
     170              : }
     171              : 
     172              : 
     173              : /**
     174              :  * Handle a #TALER_HELPER_RSA_MT_AVAIL message from the helper.
     175              :  *
     176              :  * @param dh helper context
     177              :  * @param hdr message that we received
     178              :  * @return #GNUNET_OK on success
     179              :  */
     180              : static enum GNUNET_GenericReturnValue
     181         2793 : handle_mt_avail (struct TALER_CRYPTO_RsaDenominationHelper *dh,
     182              :                  const struct GNUNET_MessageHeader *hdr)
     183              : {
     184         2793 :   const struct TALER_CRYPTO_RsaKeyAvailableNotification *kan
     185              :     = (const struct TALER_CRYPTO_RsaKeyAvailableNotification *) hdr;
     186         2793 :   const char *buf = (const char *) &kan[1];
     187              :   const char *section_name;
     188              :   uint16_t ps;
     189              :   uint16_t snl;
     190              : 
     191         2793 :   if (sizeof (*kan) > ntohs (hdr->size))
     192              :   {
     193            0 :     GNUNET_break_op (0);
     194            0 :     return GNUNET_SYSERR;
     195              :   }
     196         2793 :   ps = ntohs (kan->pub_size);
     197         2793 :   snl = ntohs (kan->section_name_len);
     198         2793 :   if (ntohs (hdr->size) != sizeof (*kan) + ps + snl)
     199              :   {
     200            0 :     GNUNET_break_op (0);
     201            0 :     return GNUNET_SYSERR;
     202              :   }
     203         2793 :   if (0 == snl)
     204              :   {
     205            0 :     GNUNET_break_op (0);
     206            0 :     return GNUNET_SYSERR;
     207              :   }
     208         2793 :   section_name = &buf[ps];
     209         2793 :   if ('\0' != section_name[snl - 1])
     210              :   {
     211            0 :     GNUNET_break_op (0);
     212            0 :     return GNUNET_SYSERR;
     213              :   }
     214              : 
     215              :   {
     216              :     struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub;
     217              :     struct TALER_RsaPubHashP h_rsa;
     218              : 
     219         2793 :     bs_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
     220         2793 :     bs_pub->cipher = GNUNET_CRYPTO_BSA_RSA;
     221              :     bs_pub->details.rsa_public_key
     222         5586 :       = GNUNET_CRYPTO_rsa_public_key_decode (buf,
     223         2793 :                                              ntohs (kan->pub_size));
     224         2793 :     if (NULL == bs_pub->details.rsa_public_key)
     225              :     {
     226            0 :       GNUNET_break_op (0);
     227            0 :       GNUNET_free (bs_pub);
     228            0 :       return GNUNET_SYSERR;
     229              :     }
     230         2793 :     bs_pub->rc = 1;
     231         2793 :     GNUNET_CRYPTO_rsa_public_key_hash (bs_pub->details.rsa_public_key,
     232              :                                        &bs_pub->pub_key_hash);
     233         2793 :     h_rsa.hash = bs_pub->pub_key_hash;
     234         2793 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     235              :                 "Received RSA key %s (%s)\n",
     236              :                 GNUNET_h2s (&bs_pub->pub_key_hash),
     237              :                 section_name);
     238         2793 :     if (GNUNET_OK !=
     239         2793 :         TALER_exchange_secmod_rsa_verify (
     240              :           &h_rsa,
     241              :           section_name,
     242              :           GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
     243              :           GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
     244              :           &kan->secm_pub,
     245              :           &kan->secm_sig))
     246              :     {
     247            0 :       GNUNET_break_op (0);
     248            0 :       GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
     249            0 :       return GNUNET_SYSERR;
     250              :     }
     251         2793 :     dh->dkc (dh->dkc_cls,
     252              :              section_name,
     253              :              GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
     254              :              GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
     255              :              &h_rsa,
     256              :              bs_pub,
     257              :              &kan->secm_pub,
     258              :              &kan->secm_sig);
     259         2793 :     GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
     260              :   }
     261         2793 :   return GNUNET_OK;
     262              : }
     263              : 
     264              : 
     265              : /**
     266              :  * Handle a #TALER_HELPER_RSA_MT_PURGE message from the helper.
     267              :  *
     268              :  * @param dh helper context
     269              :  * @param hdr message that we received
     270              :  * @return #GNUNET_OK on success
     271              :  */
     272              : static enum GNUNET_GenericReturnValue
     273            3 : handle_mt_purge (struct TALER_CRYPTO_RsaDenominationHelper *dh,
     274              :                  const struct GNUNET_MessageHeader *hdr)
     275              : {
     276            3 :   const struct TALER_CRYPTO_RsaKeyPurgeNotification *pn
     277              :     = (const struct TALER_CRYPTO_RsaKeyPurgeNotification *) hdr;
     278              : 
     279            3 :   if (sizeof (*pn) != ntohs (hdr->size))
     280              :   {
     281            0 :     GNUNET_break_op (0);
     282            0 :     return GNUNET_SYSERR;
     283              :   }
     284            3 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     285              :               "Received revocation of denomination key %s\n",
     286              :               GNUNET_h2s (&pn->h_rsa.hash));
     287            3 :   dh->dkc (dh->dkc_cls,
     288              :            NULL,
     289            3 :            GNUNET_TIME_UNIT_ZERO_TS,
     290            3 :            GNUNET_TIME_UNIT_ZERO,
     291              :            &pn->h_rsa,
     292              :            NULL,
     293              :            NULL,
     294              :            NULL);
     295            3 :   return GNUNET_OK;
     296              : }
     297              : 
     298              : 
     299              : void
     300          837 : TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *dh)
     301              : {
     302              :   char buf[UINT16_MAX];
     303          837 :   size_t off = 0;
     304          837 :   unsigned int retry_limit = 3;
     305          837 :   const struct GNUNET_MessageHeader *hdr
     306              :     = (const struct GNUNET_MessageHeader *) buf;
     307              : 
     308          837 :   if (GNUNET_OK !=
     309          837 :       try_connect (dh))
     310            0 :     return; /* give up */
     311              :   while (1)
     312           41 :   {
     313              :     uint16_t msize;
     314              :     ssize_t ret;
     315              : 
     316          878 :     ret = recv (dh->sock,
     317              :                 buf + off,
     318              :                 sizeof (buf) - off,
     319          878 :                 (dh->synced && (0 == off))
     320              :                 ? MSG_DONTWAIT
     321              :                 : 0);
     322          878 :     if (ret < 0)
     323              :     {
     324          837 :       if (EINTR == errno)
     325            0 :         continue;
     326          837 :       if (EAGAIN == errno)
     327              :       {
     328          837 :         GNUNET_assert (dh->synced);
     329          837 :         GNUNET_assert (0 == off);
     330          837 :         break;
     331              :       }
     332            0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     333              :                            "recv");
     334            0 :       do_disconnect (dh);
     335            0 :       if (0 == retry_limit)
     336            0 :         return; /* give up */
     337            0 :       if (GNUNET_OK !=
     338            0 :           try_connect (dh))
     339            0 :         return; /* give up */
     340            0 :       retry_limit--;
     341            0 :       continue;
     342              :     }
     343           41 :     if (0 == ret)
     344              :     {
     345            0 :       GNUNET_break (0 == off);
     346            0 :       return;
     347              :     }
     348           41 :     off += ret;
     349         2863 : more:
     350         2863 :     if (off < sizeof (struct GNUNET_MessageHeader))
     351           31 :       continue;
     352         2832 :     msize = ntohs (hdr->size);
     353         2832 :     if (off < msize)
     354           10 :       continue;
     355         2822 :     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     356              :                 "Received message of type %u and length %u\n",
     357              :                 (unsigned int) ntohs (hdr->type),
     358              :                 (unsigned int) msize);
     359         2822 :     switch (ntohs (hdr->type))
     360              :     {
     361         2793 :     case TALER_HELPER_RSA_MT_AVAIL:
     362         2793 :       if (GNUNET_OK !=
     363         2793 :           handle_mt_avail (dh,
     364              :                            hdr))
     365              :       {
     366            0 :         GNUNET_break_op (0);
     367            0 :         do_disconnect (dh);
     368            0 :         return;
     369              :       }
     370         2793 :       break;
     371            3 :     case TALER_HELPER_RSA_MT_PURGE:
     372            3 :       if (GNUNET_OK !=
     373            3 :           handle_mt_purge (dh,
     374              :                            hdr))
     375              :       {
     376            0 :         GNUNET_break_op (0);
     377            0 :         do_disconnect (dh);
     378            0 :         return;
     379              :       }
     380            3 :       break;
     381           26 :     case TALER_HELPER_RSA_SYNCED:
     382           26 :       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     383              :                   "Now synchronized with RSA helper\n");
     384           26 :       dh->synced = true;
     385           26 :       break;
     386            0 :     default:
     387            0 :       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     388              :                   "Received unexpected message of type %d (len: %u)\n",
     389              :                   (unsigned int) ntohs (hdr->type),
     390              :                   (unsigned int) msize);
     391            0 :       GNUNET_break_op (0);
     392            0 :       do_disconnect (dh);
     393            0 :       return;
     394              :     }
     395         2822 :     memmove (buf,
     396         2822 :              &buf[msize],
     397              :              off - msize);
     398         2822 :     off -= msize;
     399         2822 :     goto more;
     400              :   }
     401              : }
     402              : 
     403              : 
     404              : enum TALER_ErrorCode
     405          907 : TALER_CRYPTO_helper_rsa_sign (
     406              :   struct TALER_CRYPTO_RsaDenominationHelper *dh,
     407              :   const struct TALER_CRYPTO_RsaSignRequest *rsr,
     408              :   struct TALER_BlindedDenominationSignature *bs)
     409              : {
     410          907 :   enum TALER_ErrorCode ec = TALER_EC_INVALID;
     411              : 
     412          907 :   memset (bs,
     413              :           0,
     414              :           sizeof (*bs));
     415          907 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     416              :               "Starting signature process\n");
     417          907 :   if (GNUNET_OK !=
     418          907 :       try_connect (dh))
     419              :   {
     420            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     421              :                 "Failed to connect to helper\n");
     422            0 :     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     423              :   }
     424              : 
     425          907 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     426              :               "Requesting signature\n");
     427          907 :   {
     428         1814 :     char buf[sizeof (struct TALER_CRYPTO_SignRequest) + rsr->msg_size];
     429          907 :     struct TALER_CRYPTO_SignRequest *sr
     430              :       = (struct TALER_CRYPTO_SignRequest *) buf;
     431              : 
     432          907 :     sr->header.size = htons (sizeof (buf));
     433          907 :     sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
     434          907 :     sr->reserved = htonl (0);
     435          907 :     sr->h_rsa = *rsr->h_rsa;
     436          907 :     GNUNET_memcpy (&sr[1],
     437              :                    rsr->msg,
     438              :                    rsr->msg_size);
     439          907 :     if (GNUNET_OK !=
     440          907 :         TALER_crypto_helper_send_all (dh->sock,
     441              :                                       buf,
     442              :                                       sizeof (buf)))
     443              :     {
     444            0 :       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     445              :                            "send");
     446            0 :       do_disconnect (dh);
     447            0 :       return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     448              :     }
     449              :   }
     450              : 
     451          907 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     452              :               "Awaiting reply\n");
     453              :   {
     454              :     char buf[UINT16_MAX];
     455          907 :     size_t off = 0;
     456          907 :     const struct GNUNET_MessageHeader *hdr
     457              :       = (const struct GNUNET_MessageHeader *) buf;
     458          907 :     bool finished = false;
     459              : 
     460              :     while (1)
     461          907 :     {
     462              :       uint16_t msize;
     463              :       ssize_t ret;
     464              : 
     465         2721 :       ret = recv (dh->sock,
     466         1814 :                   &buf[off],
     467              :                   sizeof (buf) - off,
     468          907 :                   (finished && (0 == off))
     469              :                   ? MSG_DONTWAIT
     470              :                   : 0);
     471         1814 :       if (ret < 0)
     472              :       {
     473          907 :         if (EINTR == errno)
     474            0 :           continue;
     475          907 :         if (EAGAIN == errno)
     476              :         {
     477          907 :           GNUNET_assert (finished);
     478          907 :           GNUNET_assert (0 == off);
     479          907 :           return ec;
     480              :         }
     481            0 :         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     482              :                              "recv");
     483            0 :         do_disconnect (dh);
     484            0 :         ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     485            0 :         break;
     486              :       }
     487          907 :       if (0 == ret)
     488              :       {
     489            0 :         GNUNET_break (0 == off);
     490            0 :         if (! finished)
     491            0 :           ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     492            0 :         return ec;
     493              :       }
     494          907 :       off += ret;
     495         1814 : more:
     496         1814 :       if (off < sizeof (struct GNUNET_MessageHeader))
     497          907 :         continue;
     498          907 :       msize = ntohs (hdr->size);
     499          907 :       if (off < msize)
     500            0 :         continue;
     501          907 :       switch (ntohs (hdr->type))
     502              :       {
     503          901 :       case TALER_HELPER_RSA_MT_RES_SIGNATURE:
     504          901 :         if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
     505              :         {
     506            0 :           GNUNET_break_op (0);
     507            0 :           do_disconnect (dh);
     508            0 :           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     509            0 :           goto end;
     510              :         }
     511          901 :         if (finished)
     512              :         {
     513            0 :           GNUNET_break_op (0);
     514            0 :           do_disconnect (dh);
     515            0 :           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     516            0 :           goto end;
     517              :         }
     518              :         {
     519          901 :           const struct TALER_CRYPTO_SignResponse *sr =
     520              :             (const struct TALER_CRYPTO_SignResponse *) buf;
     521              :           struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
     522              :           struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
     523              : 
     524          901 :           rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
     525          901 :             &sr[1],
     526              :             msize - sizeof (*sr));
     527          901 :           if (NULL == rsa_signature)
     528              :           {
     529            0 :             GNUNET_break_op (0);
     530            0 :             do_disconnect (dh);
     531            0 :             ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     532            0 :             goto end;
     533              :           }
     534          901 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     535              :                       "Received signature\n");
     536          901 :           ec = TALER_EC_NONE;
     537          901 :           finished = true;
     538          901 :           blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
     539          901 :           blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
     540          901 :           blind_sig->rc = 1;
     541          901 :           blind_sig->details.blinded_rsa_signature = rsa_signature;
     542          901 :           bs->blinded_sig = blind_sig;
     543          901 :           break;
     544              :         }
     545            6 :       case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
     546            6 :         if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
     547              :         {
     548            0 :           GNUNET_break_op (0);
     549            0 :           do_disconnect (dh);
     550            0 :           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     551            0 :           goto end;
     552              :         }
     553              :         {
     554            6 :           const struct TALER_CRYPTO_SignFailure *sf =
     555              :             (const struct TALER_CRYPTO_SignFailure *) buf;
     556              : 
     557            6 :           ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
     558            6 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     559              :                       "Signing failed!\n");
     560            6 :           finished = true;
     561            6 :           break;
     562              :         }
     563            0 :       case TALER_HELPER_RSA_MT_AVAIL:
     564            0 :         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     565              :                     "Received new key!\n");
     566            0 :         if (GNUNET_OK !=
     567            0 :             handle_mt_avail (dh,
     568              :                              hdr))
     569              :         {
     570            0 :           GNUNET_break_op (0);
     571            0 :           do_disconnect (dh);
     572            0 :           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     573            0 :           goto end;
     574              :         }
     575            0 :         break; /* while(1) loop ensures we recvfrom() again */
     576            0 :       case TALER_HELPER_RSA_MT_PURGE:
     577            0 :         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     578              :                     "Received revocation!\n");
     579            0 :         if (GNUNET_OK !=
     580            0 :             handle_mt_purge (dh,
     581              :                              hdr))
     582              :         {
     583            0 :           GNUNET_break_op (0);
     584            0 :           do_disconnect (dh);
     585            0 :           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     586            0 :           goto end;
     587              :         }
     588            0 :         break; /* while(1) loop ensures we recvfrom() again */
     589            0 :       case TALER_HELPER_RSA_SYNCED:
     590            0 :         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     591              :                     "Synchronized add odd time with RSA helper!\n");
     592            0 :         dh->synced = true;
     593            0 :         break;
     594            0 :       default:
     595            0 :         GNUNET_break_op (0);
     596            0 :         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     597              :                     "Received unexpected message of type %u\n",
     598              :                     ntohs (hdr->type));
     599            0 :         do_disconnect (dh);
     600            0 :         ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     601            0 :         goto end;
     602              :       }
     603          907 :       memmove (buf,
     604          907 :                &buf[msize],
     605              :                off - msize);
     606          907 :       off -= msize;
     607          907 :       goto more;
     608              :     } /* while(1) */
     609            0 : end:
     610            0 :     if (finished)
     611            0 :       TALER_blinded_denom_sig_free (bs);
     612            0 :     return ec;
     613              :   }
     614              : }
     615              : 
     616              : 
     617              : enum TALER_ErrorCode
     618           70 : TALER_CRYPTO_helper_rsa_batch_sign (
     619              :   struct TALER_CRYPTO_RsaDenominationHelper *dh,
     620              :   unsigned int rsrs_length,
     621              :   const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length],
     622              :   struct TALER_BlindedDenominationSignature bss[static rsrs_length])
     623           70 : {
     624           70 :   enum TALER_ErrorCode ec = TALER_EC_INVALID;
     625              :   unsigned int rpos;
     626              :   unsigned int rend;
     627              :   unsigned int wpos;
     628              : 
     629           70 :   memset (bss,
     630              :           0,
     631              :           sizeof (*bss) * rsrs_length);
     632           70 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     633              :               "Starting signature process\n");
     634           70 :   if (GNUNET_OK !=
     635           70 :       try_connect (dh))
     636              :   {
     637            0 :     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     638              :                 "Failed to connect to helper\n");
     639            0 :     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     640              :   }
     641           70 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     642              :               "Requesting %u signatures\n",
     643              :               rsrs_length);
     644           70 :   rpos = 0;
     645           70 :   rend = 0;
     646           70 :   wpos = 0;
     647          140 :   while (rpos < rsrs_length)
     648              :   {
     649           70 :     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
     650              : 
     651          653 :     while ( (rend < rsrs_length) &&
     652              :             (mlen
     653              :              + sizeof (struct TALER_CRYPTO_SignRequest)
     654          583 :              + rsrs[rend].msg_size < UINT16_MAX) )
     655              :     {
     656          583 :       mlen += sizeof (struct TALER_CRYPTO_SignRequest) + rsrs[rend].msg_size;
     657          583 :       rend++;
     658              :     }
     659           70 :     {
     660           70 :       char obuf[mlen] GNUNET_ALIGN;
     661           70 :       struct TALER_CRYPTO_BatchSignRequest *bsr
     662              :         = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
     663              :       void *wbuf;
     664              : 
     665           70 :       bsr->header.type = htons (TALER_HELPER_RSA_MT_REQ_BATCH_SIGN);
     666           70 :       bsr->header.size = htons (mlen);
     667           70 :       bsr->batch_size = htonl (rend - rpos);
     668           70 :       wbuf = &bsr[1];
     669          653 :       for (unsigned int i = rpos; i<rend; i++)
     670              :       {
     671          583 :         struct TALER_CRYPTO_SignRequest *sr = wbuf;
     672          583 :         const struct TALER_CRYPTO_RsaSignRequest *rsr = &rsrs[i];
     673              : 
     674          583 :         sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
     675          583 :         sr->header.size = htons (sizeof (*sr) + rsr->msg_size);
     676          583 :         sr->reserved = htonl (0);
     677          583 :         sr->h_rsa = *rsr->h_rsa;
     678          583 :         GNUNET_memcpy (&sr[1],
     679              :                        rsr->msg,
     680              :                        rsr->msg_size);
     681          583 :         wbuf += sizeof (*sr) + rsr->msg_size;
     682              :       }
     683           70 :       GNUNET_assert (wbuf == &obuf[mlen]);
     684           70 :       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     685              :                   "Sending batch request [%u-%u)\n",
     686              :                   rpos,
     687              :                   rend);
     688           70 :       if (GNUNET_OK !=
     689           70 :           TALER_crypto_helper_send_all (dh->sock,
     690              :                                         obuf,
     691           70 :                                         sizeof (obuf)))
     692              :       {
     693            0 :         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     694              :                              "send");
     695            0 :         do_disconnect (dh);
     696            0 :         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     697              :       }
     698              :     }
     699           70 :     rpos = rend;
     700              :     {
     701              :       char buf[UINT16_MAX];
     702           70 :       size_t off = 0;
     703           70 :       const struct GNUNET_MessageHeader *hdr
     704              :         = (const struct GNUNET_MessageHeader *) buf;
     705           70 :       bool finished = false;
     706              : 
     707              :       while (1)
     708          269 :       {
     709              :         uint16_t msize;
     710              :         ssize_t ret;
     711              : 
     712          339 :         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     713              :                     "Awaiting reply at %u (up to %u)\n",
     714              :                     wpos,
     715              :                     rend);
     716          409 :         ret = recv (dh->sock,
     717          339 :                     &buf[off],
     718              :                     sizeof (buf) - off,
     719           70 :                     (finished && (0 == off))
     720              :                   ? MSG_DONTWAIT
     721              :                   : 0);
     722          339 :         if (ret < 0)
     723              :         {
     724           70 :           if (EINTR == errno)
     725            0 :             continue;
     726           70 :           if (EAGAIN == errno)
     727              :           {
     728           70 :             GNUNET_assert (finished);
     729           70 :             GNUNET_assert (0 == off);
     730           70 :             break;
     731              :           }
     732            0 :           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     733              :                                "recv");
     734            0 :           do_disconnect (dh);
     735            0 :           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
     736            0 :           break;
     737              :         }
     738          269 :         if (0 == ret)
     739              :         {
     740            0 :           GNUNET_break (0 == off);
     741            0 :           if (! finished)
     742            0 :             ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
     743            0 :           if (TALER_EC_NONE == ec)
     744            0 :             break;
     745            0 :           return ec;
     746              :         }
     747          269 :         off += ret;
     748          852 : more:
     749          852 :         if (off < sizeof (struct GNUNET_MessageHeader))
     750          269 :           continue;
     751          583 :         msize = ntohs (hdr->size);
     752          583 :         if (off < msize)
     753            0 :           continue;
     754          583 :         switch (ntohs (hdr->type))
     755              :         {
     756          251 :         case TALER_HELPER_RSA_MT_RES_SIGNATURE:
     757          251 :           if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
     758              :           {
     759            0 :             GNUNET_break_op (0);
     760            0 :             do_disconnect (dh);
     761            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     762              :           }
     763          251 :           if (finished)
     764              :           {
     765            0 :             GNUNET_break_op (0);
     766            0 :             do_disconnect (dh);
     767            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     768              :           }
     769              :           {
     770          251 :             const struct TALER_CRYPTO_SignResponse *sr =
     771              :               (const struct TALER_CRYPTO_SignResponse *) buf;
     772              :             struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
     773              :             struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
     774              : 
     775          251 :             rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
     776          251 :               &sr[1],
     777              :               msize - sizeof (*sr));
     778          251 :             if (NULL == rsa_signature)
     779              :             {
     780            0 :               GNUNET_break_op (0);
     781            0 :               do_disconnect (dh);
     782            0 :               return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     783              :             }
     784          251 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     785              :                         "Received %u signature\n",
     786              :                         wpos);
     787          251 :             blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
     788          251 :             blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
     789          251 :             blind_sig->rc = 1;
     790          251 :             blind_sig->details.blinded_rsa_signature = rsa_signature;
     791          251 :             bss[wpos].blinded_sig = blind_sig;
     792          251 :             wpos++;
     793          251 :             if (wpos == rend)
     794              :             {
     795           58 :               if (TALER_EC_INVALID == ec)
     796           58 :                 ec = TALER_EC_NONE;
     797           58 :               finished = true;
     798              :             }
     799          251 :             break;
     800              :           }
     801          332 :         case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
     802          332 :           if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
     803              :           {
     804            0 :             GNUNET_break_op (0);
     805            0 :             do_disconnect (dh);
     806            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     807              :           }
     808              :           {
     809          332 :             const struct TALER_CRYPTO_SignFailure *sf =
     810              :               (const struct TALER_CRYPTO_SignFailure *) buf;
     811              : 
     812          332 :             ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
     813          332 :             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     814              :                         "Signing %u failed with status %d!\n",
     815              :                         wpos,
     816              :                         ec);
     817          332 :             wpos++;
     818          332 :             if (wpos == rend)
     819              :             {
     820           12 :               finished = true;
     821              :             }
     822          332 :             break;
     823              :           }
     824            0 :         case TALER_HELPER_RSA_MT_AVAIL:
     825            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     826              :                       "Received new key!\n");
     827            0 :           if (GNUNET_OK !=
     828            0 :               handle_mt_avail (dh,
     829              :                                hdr))
     830              :           {
     831            0 :             GNUNET_break_op (0);
     832            0 :             do_disconnect (dh);
     833            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     834              :           }
     835            0 :           break; /* while(1) loop ensures we recvfrom() again */
     836            0 :         case TALER_HELPER_RSA_MT_PURGE:
     837            0 :           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     838              :                       "Received revocation!\n");
     839            0 :           if (GNUNET_OK !=
     840            0 :               handle_mt_purge (dh,
     841              :                                hdr))
     842              :           {
     843            0 :             GNUNET_break_op (0);
     844            0 :             do_disconnect (dh);
     845            0 :             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     846              :           }
     847            0 :           break; /* while(1) loop ensures we recvfrom() again */
     848            0 :         case TALER_HELPER_RSA_SYNCED:
     849            0 :           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
     850              :                       "Synchronized add odd time with RSA helper!\n");
     851            0 :           dh->synced = true;
     852            0 :           break;
     853            0 :         default:
     854            0 :           GNUNET_break_op (0);
     855            0 :           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
     856              :                       "Received unexpected message of type %u\n",
     857              :                       ntohs (hdr->type));
     858            0 :           do_disconnect (dh);
     859            0 :           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
     860              :         }
     861          583 :         memmove (buf,
     862          583 :                  &buf[msize],
     863              :                  off - msize);
     864          583 :         off -= msize;
     865          583 :         goto more;
     866              :       } /* while(1) */
     867              :     } /* scope */
     868              :   }   /* while (rpos < rsrs_length) */
     869           70 :   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     870              :               "Existing with %u signatures and status %d\n",
     871              :               wpos,
     872              :               ec);
     873           70 :   return ec;
     874              : }
     875              : 
     876              : 
     877              : void
     878            3 : TALER_CRYPTO_helper_rsa_revoke (
     879              :   struct TALER_CRYPTO_RsaDenominationHelper *dh,
     880              :   const struct TALER_RsaPubHashP *h_rsa)
     881              : {
     882            3 :   struct TALER_CRYPTO_RevokeRequest rr = {
     883            3 :     .header.size = htons (sizeof (rr)),
     884            3 :     .header.type = htons (TALER_HELPER_RSA_MT_REQ_REVOKE),
     885              :     .h_rsa = *h_rsa
     886              :   };
     887              : 
     888            3 :   if (GNUNET_OK !=
     889            3 :       try_connect (dh))
     890            0 :     return; /* give up */
     891            3 :   if (GNUNET_OK !=
     892            3 :       TALER_crypto_helper_send_all (dh->sock,
     893              :                                     &rr,
     894              :                                     sizeof (rr)))
     895              :   {
     896            0 :     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     897              :                          "send");
     898            0 :     do_disconnect (dh);
     899            0 :     return;
     900              :   }
     901            3 :   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
     902              :               "Requested revocation of denomination key %s\n",
     903              :               GNUNET_h2s (&h_rsa->hash));
     904              : }
     905              : 
     906              : 
     907              : void
     908           27 : TALER_CRYPTO_helper_rsa_disconnect (
     909              :   struct TALER_CRYPTO_RsaDenominationHelper *dh)
     910              : {
     911           27 :   if (-1 != dh->sock)
     912           26 :     do_disconnect (dh);
     913           27 :   GNUNET_free (dh);
     914           27 : }
     915              : 
     916              : 
     917              : /* end of crypto_helper_denom.c */
        

Generated by: LCOV version 2.0-1