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 (20502B)


      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   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    426               "Starting signature process\n");
    427   if (GNUNET_OK !=
    428       try_connect (dh))
    429   {
    430     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    431                 "Failed to connect to helper\n");
    432     return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    433   }
    434   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    435               "Requesting %u signatures\n",
    436               rsrs_length);
    437   rpos = 0;
    438   rend = 0;
    439   wpos = 0;
    440   while (rpos < rsrs_length)
    441   {
    442     unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
    443 
    444     while ( (rend < rsrs_length) &&
    445             (mlen
    446              + sizeof (struct TALER_CRYPTO_SignRequest)
    447              + rsrs[rend].msg_size < UINT16_MAX) )
    448     {
    449       mlen += sizeof (struct TALER_CRYPTO_SignRequest) + rsrs[rend].msg_size;
    450       rend++;
    451     }
    452     {
    453       char obuf[mlen] GNUNET_ALIGN;
    454       struct TALER_CRYPTO_BatchSignRequest *bsr
    455         = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
    456       void *wbuf;
    457 
    458       bsr->header.type = htons (TALER_HELPER_RSA_MT_REQ_BATCH_SIGN);
    459       bsr->header.size = htons (mlen);
    460       bsr->batch_size = htonl (rend - rpos);
    461       wbuf = &bsr[1];
    462       for (unsigned int i = rpos; i<rend; i++)
    463       {
    464         struct TALER_CRYPTO_SignRequest *sr = wbuf;
    465         const struct TALER_CRYPTO_RsaSignRequest *rsr = &rsrs[i];
    466 
    467         sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
    468         sr->header.size = htons (sizeof (*sr) + rsr->msg_size);
    469         sr->reserved = htonl (0);
    470         sr->h_rsa = *rsr->h_rsa;
    471         GNUNET_memcpy (&sr[1],
    472                        rsr->msg,
    473                        rsr->msg_size);
    474         wbuf += sizeof (*sr) + rsr->msg_size;
    475       }
    476       GNUNET_assert (wbuf == &obuf[mlen]);
    477       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    478                   "Sending batch request [%u-%u)\n",
    479                   rpos,
    480                   rend);
    481       if (GNUNET_OK !=
    482           TALER_crypto_helper_send_all (dh->sock,
    483                                         obuf,
    484                                         sizeof (obuf)))
    485       {
    486         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    487                              "send");
    488         do_disconnect (dh);
    489         return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    490       }
    491     }
    492     rpos = rend;
    493     {
    494       char buf[UINT16_MAX];
    495       size_t off = 0;
    496       const struct GNUNET_MessageHeader *hdr
    497         = (const struct GNUNET_MessageHeader *) buf;
    498       bool finished = false;
    499 
    500       while (1)
    501       {
    502         uint16_t msize;
    503         ssize_t ret;
    504 
    505         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    506                     "Awaiting reply at %u (up to %u)\n",
    507                     wpos,
    508                     rend);
    509         ret = recv (dh->sock,
    510                     &buf[off],
    511                     sizeof (buf) - off,
    512                     (finished && (0 == off))
    513                   ? MSG_DONTWAIT
    514                   : 0);
    515         if (ret < 0)
    516         {
    517           if (EINTR == errno)
    518             continue;
    519           if (EAGAIN == errno)
    520           {
    521             GNUNET_assert (finished);
    522             GNUNET_assert (0 == off);
    523             break;
    524           }
    525           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    526                                "recv");
    527           do_disconnect (dh);
    528           ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
    529           break;
    530         }
    531         if (0 == ret)
    532         {
    533           GNUNET_break (0 == off);
    534           if (! finished)
    535             ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
    536           if (TALER_EC_NONE == ec)
    537             break;
    538           return ec;
    539         }
    540         off += ret;
    541 more:
    542         if (off < sizeof (struct GNUNET_MessageHeader))
    543           continue;
    544         msize = ntohs (hdr->size);
    545         if (msize < sizeof (struct GNUNET_MessageHeader))
    546         {
    547           GNUNET_break_op (0);
    548           do_disconnect (dh);
    549           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    550         }
    551         if (off < msize)
    552           continue;
    553         switch (ntohs (hdr->type))
    554         {
    555         case TALER_HELPER_RSA_MT_RES_SIGNATURE:
    556           if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
    557           {
    558             GNUNET_break_op (0);
    559             do_disconnect (dh);
    560             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    561           }
    562           if (finished)
    563           {
    564             GNUNET_break_op (0);
    565             do_disconnect (dh);
    566             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    567           }
    568           {
    569             const struct TALER_CRYPTO_SignResponse *sr =
    570               (const struct TALER_CRYPTO_SignResponse *) buf;
    571             struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
    572             struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
    573 
    574             rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
    575               &sr[1],
    576               msize - sizeof (*sr));
    577             if (NULL == rsa_signature)
    578             {
    579               GNUNET_break_op (0);
    580               do_disconnect (dh);
    581               return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    582             }
    583             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    584                         "Received %u signature\n",
    585                         wpos);
    586             blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
    587             blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
    588             blind_sig->rc = 1;
    589             blind_sig->details.blinded_rsa_signature = rsa_signature;
    590             bss[wpos].blinded_sig = blind_sig;
    591             wpos++;
    592             if (wpos == rend)
    593             {
    594               if (TALER_EC_INVALID == ec)
    595                 ec = TALER_EC_NONE;
    596               finished = true;
    597             }
    598             break;
    599           }
    600         case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
    601           if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
    602           {
    603             GNUNET_break_op (0);
    604             do_disconnect (dh);
    605             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    606           }
    607           {
    608             const struct TALER_CRYPTO_SignFailure *sf =
    609               (const struct TALER_CRYPTO_SignFailure *) buf;
    610 
    611             ec = (enum TALER_ErrorCode) (int) ntohl (sf->ec);
    612             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    613                         "Signing %u failed with status %d!\n",
    614                         wpos,
    615                         ec);
    616             wpos++;
    617             if (wpos == rend)
    618             {
    619               finished = true;
    620             }
    621             break;
    622           }
    623         case TALER_HELPER_RSA_MT_AVAIL:
    624           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    625                       "Received new key!\n");
    626           if (GNUNET_OK !=
    627               handle_mt_avail (dh,
    628                                hdr))
    629           {
    630             GNUNET_break_op (0);
    631             do_disconnect (dh);
    632             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    633           }
    634           break; /* while(1) loop ensures we recvfrom() again */
    635         case TALER_HELPER_RSA_MT_PURGE:
    636           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    637                       "Received revocation!\n");
    638           if (GNUNET_OK !=
    639               handle_mt_purge (dh,
    640                                hdr))
    641           {
    642             GNUNET_break_op (0);
    643             do_disconnect (dh);
    644             return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    645           }
    646           break; /* while(1) loop ensures we recvfrom() again */
    647         case TALER_HELPER_RSA_SYNCED:
    648           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    649                       "Synchronized add odd time with RSA helper!\n");
    650           dh->synced = true;
    651           break;
    652         default:
    653           GNUNET_break_op (0);
    654           GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    655                       "Received unexpected message of type %u\n",
    656                       ntohs (hdr->type));
    657           do_disconnect (dh);
    658           return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
    659         }
    660         memmove (buf,
    661                  &buf[msize],
    662                  off - msize);
    663         off -= msize;
    664         goto more;
    665       } /* while(1) */
    666     } /* scope */
    667   }   /* while (rpos < rsrs_length) */
    668   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    669               "Existing with %u signatures and status %d\n",
    670               wpos,
    671               ec);
    672   return ec;
    673 }
    674 
    675 
    676 void
    677 TALER_CRYPTO_helper_rsa_revoke (
    678   struct TALER_CRYPTO_RsaDenominationHelper *dh,
    679   const struct TALER_RsaPubHashP *h_rsa)
    680 {
    681   struct TALER_CRYPTO_RevokeRequest rr = {
    682     .header.size = htons (sizeof (rr)),
    683     .header.type = htons (TALER_HELPER_RSA_MT_REQ_REVOKE),
    684     .h_rsa = *h_rsa
    685   };
    686 
    687   if (GNUNET_OK !=
    688       try_connect (dh))
    689     return; /* give up */
    690   if (GNUNET_OK !=
    691       TALER_crypto_helper_send_all (dh->sock,
    692                                     &rr,
    693                                     sizeof (rr)))
    694   {
    695     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
    696                          "send");
    697     do_disconnect (dh);
    698     return;
    699   }
    700   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    701               "Requested revocation of denomination key %s\n",
    702               GNUNET_h2s (&h_rsa->hash));
    703 }
    704 
    705 
    706 void
    707 TALER_CRYPTO_helper_rsa_disconnect (
    708   struct TALER_CRYPTO_RsaDenominationHelper *dh)
    709 {
    710   if (-1 != dh->sock)
    711     do_disconnect (dh);
    712   GNUNET_free (dh);
    713 }
    714 
    715 
    716 /* end of crypto_helper_denom.c */