exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

crypto_helper_rsa.c (21246B)


      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/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 do_disconnect (struct TALER_CRYPTO_RsaDenominationHelper *dh)
     67 {
     68   GNUNET_break (0 == close (dh->sock));
     69   dh->sock = -1;
     70   dh->synced = false;
     71 }
     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 try_connect (struct TALER_CRYPTO_RsaDenominationHelper *dh)
     83 {
     84   if (-1 != dh->sock)
     85     return GNUNET_OK;
     86   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
     87               "Establishing connection!\n");
     88   dh->sock = socket (AF_UNIX,
     89                      SOCK_STREAM,
     90                      0);
     91   if (-1 == dh->sock)
     92   {
     93     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
     94                          "socket");
     95     return GNUNET_SYSERR;
     96   }
     97   if (0 !=
     98       connect (dh->sock,
     99                (const struct sockaddr *) &dh->sa,
    100                sizeof (dh->sa)))
    101   {
    102     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
    103                               "connect",
    104                               dh->sa.sun_path);
    105     do_disconnect (dh);
    106     return GNUNET_SYSERR;
    107   }
    108   TALER_CRYPTO_helper_rsa_poll (dh);
    109   return GNUNET_OK;
    110 }
    111 
    112 
    113 struct TALER_CRYPTO_RsaDenominationHelper *
    114 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   GNUNET_asprintf (&secname,
    125                    "%s-secmod-rsa",
    126                    section);
    127 
    128   if (GNUNET_OK !=
    129       GNUNET_CONFIGURATION_get_value_filename (cfg,
    130                                                secname,
    131                                                "UNIXPATH",
    132                                                &unixpath))
    133   {
    134     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    135                                secname,
    136                                "UNIXPATH");
    137     GNUNET_free (secname);
    138     return NULL;
    139   }
    140   /* we use >= here because we want the sun_path to always
    141      be 0-terminated */
    142   if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
    143   {
    144     GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
    145                                secname,
    146                                "UNIXPATH",
    147                                "path too long");
    148     GNUNET_free (unixpath);
    149     GNUNET_free (secname);
    150     return NULL;
    151   }
    152   GNUNET_free (secname);
    153   dh = GNUNET_new (struct TALER_CRYPTO_RsaDenominationHelper);
    154   dh->dkc = dkc;
    155   dh->dkc_cls = dkc_cls;
    156   dh->sa.sun_family = AF_UNIX;
    157   strncpy (dh->sa.sun_path,
    158            unixpath,
    159            sizeof (dh->sa.sun_path) - 1);
    160   GNUNET_free (unixpath);
    161   dh->sock = -1;
    162   if (GNUNET_OK !=
    163       try_connect (dh))
    164   {
    165     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    166                 "Could not connect to %s. Will keep trying\n",
    167                 "taler-exchange-helper-secmod-rsa");
    168   }
    169   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 handle_mt_avail (struct TALER_CRYPTO_RsaDenominationHelper *dh,
    182                  const struct GNUNET_MessageHeader *hdr)
    183 {
    184   const struct TALER_CRYPTO_RsaKeyAvailableNotification *kan
    185     = (const struct TALER_CRYPTO_RsaKeyAvailableNotification *) hdr;
    186   const char *buf = (const char *) &kan[1];
    187   const char *section_name;
    188   uint16_t ps;
    189   uint16_t snl;
    190 
    191   if (sizeof (*kan) > ntohs (hdr->size))
    192   {
    193     GNUNET_break_op (0);
    194     return GNUNET_SYSERR;
    195   }
    196   ps = ntohs (kan->pub_size);
    197   snl = ntohs (kan->section_name_len);
    198   if (ntohs (hdr->size) != sizeof (*kan) + ps + snl)
    199   {
    200     GNUNET_break_op (0);
    201     return GNUNET_SYSERR;
    202   }
    203   if (0 == snl)
    204   {
    205     GNUNET_break_op (0);
    206     return GNUNET_SYSERR;
    207   }
    208   section_name = &buf[ps];
    209   if ('\0' != section_name[snl - 1])
    210   {
    211     GNUNET_break_op (0);
    212     return GNUNET_SYSERR;
    213   }
    214 
    215   {
    216     struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub;
    217     struct TALER_RsaPubHashP h_rsa;
    218 
    219     bs_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
    220     bs_pub->cipher = GNUNET_CRYPTO_BSA_RSA;
    221     bs_pub->details.rsa_public_key
    222       = GNUNET_CRYPTO_rsa_public_key_decode (buf,
    223                                              ntohs (kan->pub_size));
    224     if (NULL == bs_pub->details.rsa_public_key)
    225     {
    226       GNUNET_break_op (0);
    227       GNUNET_free (bs_pub);
    228       return GNUNET_SYSERR;
    229     }
    230     bs_pub->rc = 1;
    231     GNUNET_CRYPTO_rsa_public_key_hash (bs_pub->details.rsa_public_key,
    232                                        &bs_pub->pub_key_hash);
    233     h_rsa.hash = bs_pub->pub_key_hash;
    234     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     if (GNUNET_OK !=
    239         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       GNUNET_break_op (0);
    248       GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
    249       return GNUNET_SYSERR;
    250     }
    251     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     GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
    260   }
    261   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 handle_mt_purge (struct TALER_CRYPTO_RsaDenominationHelper *dh,
    274                  const struct GNUNET_MessageHeader *hdr)
    275 {
    276   const struct TALER_CRYPTO_RsaKeyPurgeNotification *pn
    277     = (const struct TALER_CRYPTO_RsaKeyPurgeNotification *) hdr;
    278 
    279   if (sizeof (*pn) != ntohs (hdr->size))
    280   {
    281     GNUNET_break_op (0);
    282     return GNUNET_SYSERR;
    283   }
    284   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    285               "Received revocation of denomination key %s\n",
    286               GNUNET_h2s (&pn->h_rsa.hash));
    287   dh->dkc (dh->dkc_cls,
    288            NULL,
    289            GNUNET_TIME_UNIT_ZERO_TS,
    290            GNUNET_TIME_UNIT_ZERO,
    291            &pn->h_rsa,
    292            NULL,
    293            NULL,
    294            NULL);
    295   return GNUNET_OK;
    296 }
    297 
    298 
    299 void
    300 TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *dh)
    301 {
    302   char buf[UINT16_MAX];
    303   size_t off = 0;
    304   unsigned int retry_limit = 3;
    305   const struct GNUNET_MessageHeader *hdr
    306     = (const struct GNUNET_MessageHeader *) buf;
    307 
    308   if (GNUNET_OK !=
    309       try_connect (dh))
    310     return; /* give up */
    311   while (1)
    312   {
    313     uint16_t msize;
    314     ssize_t ret;
    315 
    316     ret = recv (dh->sock,
    317                 buf + off,
    318                 sizeof (buf) - off,
    319                 (dh->synced && (0 == off))
    320                 ? MSG_DONTWAIT
    321                 : 0);
    322     if (ret < 0)
    323     {
    324       if (EINTR == errno)
    325         continue;
    326       if (EAGAIN == errno)
    327       {
    328         GNUNET_assert (dh->synced);
    329         GNUNET_assert (0 == off);
    330         break;
    331       }
    332       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    333                            "recv");
    334       do_disconnect (dh);
    335       if (0 == retry_limit)
    336         return; /* give up */
    337       if (GNUNET_OK !=
    338           try_connect (dh))
    339         return; /* give up */
    340       retry_limit--;
    341       continue;
    342     }
    343     if (0 == ret)
    344     {
    345       GNUNET_break (0 == off);
    346       return;
    347     }
    348     off += ret;
    349 more:
    350     if (off < sizeof (struct GNUNET_MessageHeader))
    351       continue;
    352     msize = ntohs (hdr->size);
    353     if (msize < sizeof (struct GNUNET_MessageHeader))
    354     {
    355       GNUNET_break_op (0);
    356       do_disconnect (dh);
    357       return;
    358     }
    359     if (off < msize)
    360       continue;
    361     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    362                 "Received message of type %u and length %u\n",
    363                 (unsigned int) ntohs (hdr->type),
    364                 (unsigned int) msize);
    365     switch (ntohs (hdr->type))
    366     {
    367     case TALER_HELPER_RSA_MT_AVAIL:
    368       if (GNUNET_OK !=
    369           handle_mt_avail (dh,
    370                            hdr))
    371       {
    372         GNUNET_break_op (0);
    373         do_disconnect (dh);
    374         return;
    375       }
    376       break;
    377     case TALER_HELPER_RSA_MT_PURGE:
    378       if (GNUNET_OK !=
    379           handle_mt_purge (dh,
    380                            hdr))
    381       {
    382         GNUNET_break_op (0);
    383         do_disconnect (dh);
    384         return;
    385       }
    386       break;
    387     case TALER_HELPER_RSA_SYNCED:
    388       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    389                   "Now synchronized with RSA helper\n");
    390       dh->synced = true;
    391       break;
    392     default:
    393       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    394                   "Received unexpected message of type %d (len: %u)\n",
    395                   (unsigned int) ntohs (hdr->type),
    396                   (unsigned int) msize);
    397       GNUNET_break_op (0);
    398       do_disconnect (dh);
    399       return;
    400     }
    401     memmove (buf,
    402              &buf[msize],
    403              off - msize);
    404     off -= msize;
    405     goto more;
    406   }
    407 }
    408 
    409 
    410 enum TALER_ErrorCode
    411 TALER_CRYPTO_helper_rsa_batch_sign (
    412   struct TALER_CRYPTO_RsaDenominationHelper *dh,
    413   unsigned int rsrs_length,
    414   const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length],
    415   struct TALER_BlindedDenominationSignature bss[static rsrs_length])
    416 {
    417   enum TALER_ErrorCode ec = TALER_EC_INVALID;
    418   unsigned int rpos;
    419   unsigned int rend;
    420   unsigned int wpos;
    421 
    422   memset (bss,
    423           0,
    424           sizeof (*bss) * rsrs_length);
    425   /* Every request must fit into an IPC message of its own, together
    426      with the batch header; otherwise it could never be transmitted. */
    427   for (unsigned int i = 0; i<rsrs_length; i++)
    428   {
    429     if (rsrs[i].msg_size >=
    430         UINT16_MAX
    431         - sizeof (struct TALER_CRYPTO_BatchSignRequest)
    432         - sizeof (struct TALER_CRYPTO_SignRequest))
    433     {
    434       GNUNET_break_op (0);
    435       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    436                   "Message to sign is too large (%llu bytes)\n",
    437                   (unsigned long long) rsrs[i].msg_size);
    438       return TALER_EC_GENERIC_PARAMETER_MALFORMED;
    439     }
    440   }
    441   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    442               "Starting signature process\n");
    443   if (GNUNET_OK !=
    444       try_connect (dh))
    445   {
    446     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    447                 "Failed to connect to helper\n");
    448     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    449   }
    450   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    451               "Requesting %u signatures\n",
    452               rsrs_length);
    453   rpos = 0;
    454   rend = 0;
    455   wpos = 0;
    456   while (rpos < rsrs_length)
    457   {
    458     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
    459 
    460     /* as each individual request fits, this loop always advances rend
    461        at least once, and thus the outer loop makes progress */
    462     while ( (rend < rsrs_length) &&
    463             (mlen
    464              + sizeof (struct TALER_CRYPTO_SignRequest)
    465              + rsrs[rend].msg_size < UINT16_MAX) )
    466     {
    467       mlen += sizeof (struct TALER_CRYPTO_SignRequest) + rsrs[rend].msg_size;
    468       rend++;
    469     }
    470     {
    471       char obuf[mlen] GNUNET_ALIGN;
    472       struct TALER_CRYPTO_BatchSignRequest *bsr
    473         = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
    474       void *wbuf;
    475 
    476       bsr->header.type = htons (TALER_HELPER_RSA_MT_REQ_BATCH_SIGN);
    477       bsr->header.size = htons (mlen);
    478       bsr->batch_size = htonl (rend - rpos);
    479       wbuf = &bsr[1];
    480       for (unsigned int i = rpos; i<rend; i++)
    481       {
    482         struct TALER_CRYPTO_SignRequest *sr = wbuf;
    483         const struct TALER_CRYPTO_RsaSignRequest *rsr = &rsrs[i];
    484 
    485         sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
    486         sr->header.size = htons (sizeof (*sr) + rsr->msg_size);
    487         sr->reserved = htonl (0);
    488         sr->h_rsa = *rsr->h_rsa;
    489         GNUNET_memcpy (&sr[1],
    490                        rsr->msg,
    491                        rsr->msg_size);
    492         wbuf += sizeof (*sr) + rsr->msg_size;
    493       }
    494       GNUNET_assert (wbuf == &obuf[mlen]);
    495       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    496                   "Sending batch request [%u-%u)\n",
    497                   rpos,
    498                   rend);
    499       if (GNUNET_OK !=
    500           TALER_crypto_helper_send_all (dh->sock,
    501                                         obuf,
    502                                         sizeof (obuf)))
    503       {
    504         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    505                              "send");
    506         do_disconnect (dh);
    507         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    508       }
    509     }
    510     rpos = rend;
    511     {
    512       char buf[UINT16_MAX];
    513       size_t off = 0;
    514       const struct GNUNET_MessageHeader *hdr
    515         = (const struct GNUNET_MessageHeader *) buf;
    516       bool finished = false;
    517 
    518       while (1)
    519       {
    520         uint16_t msize;
    521         ssize_t ret;
    522 
    523         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    524                     "Awaiting reply at %u (up to %u)\n",
    525                     wpos,
    526                     rend);
    527         ret = recv (dh->sock,
    528                     &buf[off],
    529                     sizeof (buf) - off,
    530                     (finished && (0 == off))
    531                   ? MSG_DONTWAIT
    532                   : 0);
    533         if (ret < 0)
    534         {
    535           if (EINTR == errno)
    536             continue;
    537           if (EAGAIN == errno)
    538           {
    539             GNUNET_assert (finished);
    540             GNUNET_assert (0 == off);
    541             break;
    542           }
    543           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    544                                "recv");
    545           do_disconnect (dh);
    546           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    547           break;
    548         }
    549         if (0 == ret)
    550         {
    551           GNUNET_break (0 == off);
    552           if (! finished)
    553             ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
    554           if (TALER_EC_NONE == ec)
    555             break;
    556           return ec;
    557         }
    558         off += ret;
    559 more:
    560         if (off < sizeof (struct GNUNET_MessageHeader))
    561           continue;
    562         msize = ntohs (hdr->size);
    563         if (msize < sizeof (struct GNUNET_MessageHeader))
    564         {
    565           GNUNET_break_op (0);
    566           do_disconnect (dh);
    567           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    568         }
    569         if (off < msize)
    570           continue;
    571         switch (ntohs (hdr->type))
    572         {
    573         case TALER_HELPER_RSA_MT_RES_SIGNATURE:
    574           if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
    575           {
    576             GNUNET_break_op (0);
    577             do_disconnect (dh);
    578             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    579           }
    580           if (finished)
    581           {
    582             GNUNET_break_op (0);
    583             do_disconnect (dh);
    584             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    585           }
    586           {
    587             const struct TALER_CRYPTO_SignResponse *sr =
    588               (const struct TALER_CRYPTO_SignResponse *) buf;
    589             struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
    590             struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
    591 
    592             rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
    593               &sr[1],
    594               msize - sizeof (*sr));
    595             if (NULL == rsa_signature)
    596             {
    597               GNUNET_break_op (0);
    598               do_disconnect (dh);
    599               return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    600             }
    601             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    602                         "Received %u signature\n",
    603                         wpos);
    604             blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
    605             blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
    606             blind_sig->rc = 1;
    607             blind_sig->details.blinded_rsa_signature = rsa_signature;
    608             bss[wpos].blinded_sig = blind_sig;
    609             wpos++;
    610             if (wpos == rend)
    611             {
    612               if (TALER_EC_INVALID == ec)
    613                 ec = TALER_EC_NONE;
    614               finished = true;
    615             }
    616             break;
    617           }
    618         case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
    619           if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
    620           {
    621             GNUNET_break_op (0);
    622             do_disconnect (dh);
    623             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    624           }
    625           {
    626             const struct TALER_CRYPTO_SignFailure *sf =
    627               (const struct TALER_CRYPTO_SignFailure *) buf;
    628 
    629             ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
    630             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    631                         "Signing %u failed with status %d!\n",
    632                         wpos,
    633                         ec);
    634             wpos++;
    635             if (wpos == rend)
    636             {
    637               finished = true;
    638             }
    639             break;
    640           }
    641         case TALER_HELPER_RSA_MT_AVAIL:
    642           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    643                       "Received new key!\n");
    644           if (GNUNET_OK !=
    645               handle_mt_avail (dh,
    646                                hdr))
    647           {
    648             GNUNET_break_op (0);
    649             do_disconnect (dh);
    650             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    651           }
    652           break; /* while(1) loop ensures we recvfrom() again */
    653         case TALER_HELPER_RSA_MT_PURGE:
    654           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    655                       "Received revocation!\n");
    656           if (GNUNET_OK !=
    657               handle_mt_purge (dh,
    658                                hdr))
    659           {
    660             GNUNET_break_op (0);
    661             do_disconnect (dh);
    662             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    663           }
    664           break; /* while(1) loop ensures we recvfrom() again */
    665         case TALER_HELPER_RSA_SYNCED:
    666           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    667                       "Synchronized add odd time with RSA helper!\n");
    668           dh->synced = true;
    669           break;
    670         default:
    671           GNUNET_break_op (0);
    672           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    673                       "Received unexpected message of type %u\n",
    674                       ntohs (hdr->type));
    675           do_disconnect (dh);
    676           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    677         }
    678         memmove (buf,
    679                  &buf[msize],
    680                  off - msize);
    681         off -= msize;
    682         goto more;
    683       } /* while(1) */
    684     } /* scope */
    685   }   /* while (rpos < rsrs_length) */
    686   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    687               "Existing with %u signatures and status %d\n",
    688               wpos,
    689               ec);
    690   return ec;
    691 }
    692 
    693 
    694 void
    695 TALER_CRYPTO_helper_rsa_revoke (
    696   struct TALER_CRYPTO_RsaDenominationHelper *dh,
    697   const struct TALER_RsaPubHashP *h_rsa)
    698 {
    699   struct TALER_CRYPTO_RevokeRequest rr = {
    700     .header.size = htons (sizeof (rr)),
    701     .header.type = htons (TALER_HELPER_RSA_MT_REQ_REVOKE),
    702     .h_rsa = *h_rsa
    703   };
    704 
    705   if (GNUNET_OK !=
    706       try_connect (dh))
    707     return; /* give up */
    708   if (GNUNET_OK !=
    709       TALER_crypto_helper_send_all (dh->sock,
    710                                     &rr,
    711                                     sizeof (rr)))
    712   {
    713     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    714                          "send");
    715     do_disconnect (dh);
    716     return;
    717   }
    718   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    719               "Requested revocation of denomination key %s\n",
    720               GNUNET_h2s (&h_rsa->hash));
    721 }
    722 
    723 
    724 void
    725 TALER_CRYPTO_helper_rsa_disconnect (
    726   struct TALER_CRYPTO_RsaDenominationHelper *dh)
    727 {
    728   if (-1 != dh->sock)
    729     do_disconnect (dh);
    730   GNUNET_free (dh);
    731 }
    732 
    733 
    734 /* end of crypto_helper_denom.c */