LCOV - code coverage report
Current view: top level - util - crypto_helper_rsa.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 280 455 61.5 %
Date: 2025-06-05 21:03:14 Functions: 10 10 100.0 %

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

Generated by: LCOV version 1.16