summaryrefslogtreecommitdiff
path: root/src/util/crypto_helper_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/crypto_helper_cs.c')
-rw-r--r--src/util/crypto_helper_cs.c645
1 files changed, 533 insertions, 112 deletions
diff --git a/src/util/crypto_helper_cs.c b/src/util/crypto_helper_cs.c
index e12d5ad61..4c4a56feb 100644
--- a/src/util/crypto_helper_cs.c
+++ b/src/util/crypto_helper_cs.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2020, 2021 Taler Systems SA
+ Copyright (C) 2020, 2021, 2022 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
@@ -113,21 +113,27 @@ try_connect (struct TALER_CRYPTO_CsDenominationHelper *dh)
struct TALER_CRYPTO_CsDenominationHelper *
TALER_CRYPTO_helper_cs_connect (
const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
TALER_CRYPTO_CsDenominationKeyStatusCallback dkc,
void *dkc_cls)
{
struct TALER_CRYPTO_CsDenominationHelper *dh;
char *unixpath;
+ char *secname;
+ GNUNET_asprintf (&secname,
+ "%s-secmod-cs",
+ section);
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
- "taler-exchange-secmod-cs",
+ secname,
"UNIXPATH",
&unixpath))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-cs",
+ secname,
"UNIXPATH");
+ GNUNET_free (secname);
return NULL;
}
/* we use >= here because we want the sun_path to always
@@ -135,12 +141,14 @@ TALER_CRYPTO_helper_cs_connect (
if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- "taler-exchange-secmod-cs",
+ secname,
"UNIXPATH",
"path too long");
GNUNET_free (unixpath);
+ GNUNET_free (secname);
return NULL;
}
+ GNUNET_free (secname);
dh = GNUNET_new (struct TALER_CRYPTO_CsDenominationHelper);
dh->dkc = dkc;
dh->dkc_cls = dkc_cls;
@@ -201,13 +209,18 @@ handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
}
{
- struct TALER_DenominationPublicKey denom_pub;
+ struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
struct TALER_CsPubHashP h_cs;
- denom_pub.cipher = TALER_DENOMINATION_CS;
- denom_pub.details.cs_public_key = kan->denom_pub;
+ bsign_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+ bsign_pub->cipher = GNUNET_CRYPTO_BSA_CS;
+ bsign_pub->rc = 1;
+ bsign_pub->details.cs_public_key = kan->denom_pub;
- TALER_cs_pub_hash (&denom_pub.details.cs_public_key, &h_cs);
+ GNUNET_CRYPTO_hash (&bsign_pub->details.cs_public_key,
+ sizeof (bsign_pub->details.cs_public_key),
+ &bsign_pub->pub_key_hash);
+ h_cs.hash = bsign_pub->pub_key_hash;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received CS key %s (%s)\n",
GNUNET_h2s (&h_cs.hash),
@@ -222,7 +235,7 @@ handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
&kan->secm_sig))
{
GNUNET_break_op (0);
- TALER_denom_pub_free (&denom_pub);
+ GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
return GNUNET_SYSERR;
}
dh->dkc (dh->dkc_cls,
@@ -230,10 +243,10 @@ handle_mt_avail (struct TALER_CRYPTO_CsDenominationHelper *dh,
GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
&h_cs,
- &denom_pub,
+ bsign_pub,
&kan->secm_pub,
&kan->secm_sig);
- TALER_denom_pub_free (&denom_pub);
+ GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
}
return GNUNET_OK;
}
@@ -378,34 +391,19 @@ more:
}
-/**
- * Request helper @a dh to sign @a msg using the public key corresponding to
- * @a h_denom_pub.
- *
- * This operation will block until the signature has been obtained. Should
- * this process receive a signal (that is not ignored) while the operation is
- * pending, the operation will fail. Note that the helper may still believe
- * that it created the signature. Thus, signals may result in a small
- * differences in the signature counters. Retrying in this case may work.
- *
- * @param dh helper process connection
- * @param h_cs hash of the CS public key to use to sign
- * @param blinded_planchet blinded planchet containing c and nonce
- * @param for_melt true if the HKDF for melt should be used
- * @param[out] bs set to the blind signature
- * @return #TALER_EC_NONE on success
- */
-static enum TALER_ErrorCode
-helper_cs_sign (
+enum TALER_ErrorCode
+TALER_CRYPTO_helper_cs_sign (
struct TALER_CRYPTO_CsDenominationHelper *dh,
- const struct TALER_CsPubHashP *h_cs,
- const struct TALER_BlindedCsPlanchet *blinded_planchet,
+ const struct TALER_CRYPTO_CsSignRequest *req,
bool for_melt,
struct TALER_BlindedDenominationSignature *bs)
{
enum TALER_ErrorCode ec = TALER_EC_INVALID;
+ const struct TALER_CsPubHashP *h_cs = req->h_cs;
- bs->cipher = TALER_DENOMINATION_INVALID;
+ memset (bs,
+ 0,
+ sizeof (*bs));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Starting signature process\n");
if (GNUNET_OK !=
@@ -419,15 +417,15 @@ helper_cs_sign (
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Requesting signature\n");
{
- char buf[sizeof (struct TALER_CRYPTO_CsSignRequest)];
- struct TALER_CRYPTO_CsSignRequest *sr
- = (struct TALER_CRYPTO_CsSignRequest *) buf;
+ char buf[sizeof (struct TALER_CRYPTO_CsSignRequestMessage)];
+ struct TALER_CRYPTO_CsSignRequestMessage *sr
+ = (struct TALER_CRYPTO_CsSignRequestMessage *) buf;
sr->header.size = htons (sizeof (buf));
sr->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
sr->for_melt = htonl (for_melt ? 1 : 0);
sr->h_cs = *h_cs;
- sr->planchet = *blinded_planchet;
+ sr->message = *req->blinded_planchet;
if (GNUNET_OK !=
TALER_crypto_helper_send_all (dh->sock,
buf,
@@ -493,7 +491,7 @@ more:
switch (ntohs (hdr->type))
{
case TALER_HELPER_CS_MT_RES_SIGNATURE:
- if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
+ if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
{
GNUNET_break_op (0);
do_disconnect (dh);
@@ -510,13 +508,18 @@ more:
{
const struct TALER_CRYPTO_SignResponse *sr =
(const struct TALER_CRYPTO_SignResponse *) buf;
+ struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Received signature\n");
ec = TALER_EC_NONE;
finished = true;
- bs->cipher = TALER_DENOMINATION_CS;
- bs->details.blinded_cs_answer = sr->cs_answer;
+ blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+ blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
+ blinded_sig->rc = 1;
+ blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
+ blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
+ bs->blinded_sig = blinded_sig;
break;
}
case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
@@ -533,7 +536,8 @@ more:
ec = (enum TALER_ErrorCode) ntohl (sf->ec);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Signing failed!\n");
+ "Signing failed with status %d!\n",
+ ec);
finished = true;
break;
}
@@ -591,36 +595,6 @@ end:
}
-enum TALER_ErrorCode
-TALER_CRYPTO_helper_cs_sign_melt (
- struct TALER_CRYPTO_CsDenominationHelper *dh,
- const struct TALER_CsPubHashP *h_cs,
- const struct TALER_BlindedCsPlanchet *blinded_planchet,
- struct TALER_BlindedDenominationSignature *bs)
-{
- return helper_cs_sign (dh,
- h_cs,
- blinded_planchet,
- true,
- bs);
-}
-
-
-enum TALER_ErrorCode
-TALER_CRYPTO_helper_cs_sign_withdraw (
- struct TALER_CRYPTO_CsDenominationHelper *dh,
- const struct TALER_CsPubHashP *h_cs,
- const struct TALER_BlindedCsPlanchet *blinded_planchet,
- struct TALER_BlindedDenominationSignature *bs)
-{
- return helper_cs_sign (dh,
- h_cs,
- blinded_planchet,
- false,
- bs);
-}
-
-
void
TALER_CRYPTO_helper_cs_revoke (
struct TALER_CRYPTO_CsDenominationHelper *dh,
@@ -651,31 +625,15 @@ TALER_CRYPTO_helper_cs_revoke (
}
-/**
- * Ask the helper to derive R using the @a nonce and denomination key
- * associated with @a h_cs.
- *
- * This operation will block until the R has been obtained. Should
- * this process receive a signal (that is not ignored) while the operation is
- * pending, the operation will fail. Note that the helper may still believe
- * that it created the signature. Thus, signals may result in a small
- * differences in the signature counters. Retrying in this case may work.
- *
- * @param dh helper to process connection
- * @param h_cs hash of the CS public key to revoke
- * @param nonce witdhraw nonce
- * @param for_melt true if the HKDF for melt should be used
- * @param[out] crp set to the pair of R values
- * @return set to the error code (or #TALER_EC_NONE on success)
- */
-static enum TALER_ErrorCode
-helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
- const struct TALER_CsPubHashP *h_cs,
- const struct TALER_CsNonce *nonce,
- bool for_melt,
- struct TALER_DenominationCSPublicRPairP *crp)
+enum TALER_ErrorCode
+TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
+ const struct TALER_CRYPTO_CsDeriveRequest *cdr,
+ bool for_melt,
+ struct GNUNET_CRYPTO_CSPublicRPairP *crp)
{
enum TALER_ErrorCode ec = TALER_EC_INVALID;
+ const struct TALER_CsPubHashP *h_cs = cdr->h_cs;
+ const struct GNUNET_CRYPTO_CsSessionNonce *nonce = cdr->nonce;
memset (crp,
0,
@@ -853,32 +811,495 @@ more:
enum TALER_ErrorCode
-TALER_CRYPTO_helper_cs_r_derive_withdraw (
+TALER_CRYPTO_helper_cs_batch_sign (
struct TALER_CRYPTO_CsDenominationHelper *dh,
- const struct TALER_CsPubHashP *h_cs,
- const struct TALER_CsNonce *nonce,
- struct TALER_DenominationCSPublicRPairP *crp)
+ unsigned int reqs_length,
+ const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
+ bool for_melt,
+ struct TALER_BlindedDenominationSignature bss[static reqs_length])
{
- return helper_cs_r_derive (dh,
- h_cs,
- nonce,
- false,
- crp);
+ enum TALER_ErrorCode ec = TALER_EC_INVALID;
+ unsigned int rpos;
+ unsigned int rend;
+ unsigned int wpos;
+
+ memset (bss,
+ 0,
+ sizeof (*bss) * reqs_length);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting signature process\n");
+ if (GNUNET_OK !=
+ try_connect (dh))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to connect to helper\n");
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requesting %u signatures\n",
+ reqs_length);
+ rpos = 0;
+ rend = 0;
+ wpos = 0;
+ while (rpos < reqs_length)
+ {
+ unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
+
+ while ( (rend < reqs_length) &&
+ (mlen + sizeof (struct TALER_CRYPTO_CsSignRequestMessage)
+ < UINT16_MAX) )
+ {
+ mlen += sizeof (struct TALER_CRYPTO_CsSignRequestMessage);
+ rend++;
+ }
+ {
+ char obuf[mlen] GNUNET_ALIGN;
+ struct TALER_CRYPTO_BatchSignRequest *bsr
+ = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
+ void *wbuf;
+
+ bsr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_SIGN);
+ bsr->header.size = htons (mlen);
+ bsr->batch_size = htonl (rend - rpos);
+ wbuf = &bsr[1];
+ for (unsigned int i = rpos; i<rend; i++)
+ {
+ struct TALER_CRYPTO_CsSignRequestMessage *csm = wbuf;
+ const struct TALER_CRYPTO_CsSignRequest *csr = &reqs[i];
+
+ csm->header.size = htons (sizeof (*csm));
+ csm->header.type = htons (TALER_HELPER_CS_MT_REQ_SIGN);
+ csm->for_melt = htonl (for_melt ? 1 : 0);
+ csm->h_cs = *csr->h_cs;
+ csm->message = *csr->blinded_planchet;
+ wbuf += sizeof (*csm);
+ }
+ GNUNET_assert (wbuf == &obuf[mlen]);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending batch request [%u-%u)\n",
+ rpos,
+ rend);
+ if (GNUNET_OK !=
+ TALER_crypto_helper_send_all (dh->sock,
+ obuf,
+ sizeof (obuf)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "send");
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+ } /* end of obuf scope */
+ rpos = rend;
+ {
+ char buf[UINT16_MAX];
+ size_t off = 0;
+ const struct GNUNET_MessageHeader *hdr
+ = (const struct GNUNET_MessageHeader *) buf;
+ bool finished = false;
+
+ while (1)
+ {
+ uint16_t msize;
+ ssize_t ret;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Awaiting reply at %u (up to %u)\n",
+ wpos,
+ rend);
+ ret = recv (dh->sock,
+ &buf[off],
+ sizeof (buf) - off,
+ (finished && (0 == off))
+ ? MSG_DONTWAIT
+ : 0);
+ if (ret < 0)
+ {
+ if (EINTR == errno)
+ continue;
+ if (EAGAIN == errno)
+ {
+ GNUNET_assert (finished);
+ GNUNET_assert (0 == off);
+ break;
+ }
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "recv");
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+ if (0 == ret)
+ {
+ GNUNET_break (0 == off);
+ if (! finished)
+ return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+ if (TALER_EC_NONE == ec)
+ break;
+ return ec;
+ }
+ off += ret;
+more:
+ if (off < sizeof (struct GNUNET_MessageHeader))
+ continue;
+ msize = ntohs (hdr->size);
+ if (off < msize)
+ continue;
+ switch (ntohs (hdr->type))
+ {
+ case TALER_HELPER_CS_MT_RES_SIGNATURE:
+ if (msize != sizeof (struct TALER_CRYPTO_SignResponse))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ if (finished)
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ {
+ const struct TALER_CRYPTO_SignResponse *sr =
+ (const struct TALER_CRYPTO_SignResponse *) buf;
+ struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %u signature\n",
+ wpos);
+ blinded_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+ blinded_sig->cipher = GNUNET_CRYPTO_BSA_CS;
+ blinded_sig->rc = 1;
+ blinded_sig->details.blinded_cs_answer.b = ntohl (sr->b);
+ blinded_sig->details.blinded_cs_answer.s_scalar = sr->cs_answer;
+
+ bss[wpos].blinded_sig = blinded_sig;
+ wpos++;
+ if (wpos == rend)
+ {
+ if (TALER_EC_INVALID == ec)
+ ec = TALER_EC_NONE;
+ finished = true;
+ }
+ break;
+ }
+
+ case TALER_HELPER_CS_MT_RES_SIGN_FAILURE:
+ if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ {
+ const struct TALER_CRYPTO_SignFailure *sf =
+ (const struct TALER_CRYPTO_SignFailure *) buf;
+
+ ec = (enum TALER_ErrorCode) ntohl (sf->ec);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Signing %u failed with status %d!\n",
+ wpos,
+ ec);
+ wpos++;
+ if (wpos == rend)
+ {
+ finished = true;
+ }
+ break;
+ }
+ case TALER_HELPER_CS_MT_AVAIL:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received new key!\n");
+ if (GNUNET_OK !=
+ handle_mt_avail (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ break; /* while(1) loop ensures we recvfrom() again */
+ case TALER_HELPER_CS_MT_PURGE:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received revocation!\n");
+ if (GNUNET_OK !=
+ handle_mt_purge (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ break; /* while(1) loop ensures we recvfrom() again */
+ case TALER_HELPER_CS_SYNCED:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Synchronized add odd time with CS helper!\n");
+ dh->synced = true;
+ break;
+ default:
+ GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Received unexpected message of type %u\n",
+ ntohs (hdr->type));
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ memmove (buf,
+ &buf[msize],
+ off - msize);
+ off -= msize;
+ goto more;
+ } /* while(1) */
+ } /* scope */
+ } /* while (rpos < cdrs_length) */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Existing with %u signatures and status %d\n",
+ wpos,
+ ec);
+ return ec;
}
enum TALER_ErrorCode
-TALER_CRYPTO_helper_cs_r_derive_melt (
+TALER_CRYPTO_helper_cs_r_batch_derive (
struct TALER_CRYPTO_CsDenominationHelper *dh,
- const struct TALER_CsPubHashP *h_cs,
- const struct TALER_CsNonce *nonce,
- struct TALER_DenominationCSPublicRPairP *crp)
+ unsigned int cdrs_length,
+ const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
+ bool for_melt,
+ struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length])
{
- return helper_cs_r_derive (dh,
- h_cs,
- nonce,
- true,
- crp);
+ enum TALER_ErrorCode ec = TALER_EC_INVALID;
+ unsigned int rpos;
+ unsigned int rend;
+ unsigned int wpos;
+
+ memset (crps,
+ 0,
+ sizeof (*crps) * cdrs_length);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Starting R derivation process\n");
+ if (GNUNET_OK !=
+ try_connect (dh))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to connect to helper\n");
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requesting %u R pairs\n",
+ cdrs_length);
+ rpos = 0;
+ rend = 0;
+ wpos = 0;
+ while (rpos < cdrs_length)
+ {
+ unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchDeriveRequest);
+
+ while ( (rend < cdrs_length) &&
+ (mlen + sizeof (struct TALER_CRYPTO_CsRDeriveRequest)
+ < UINT16_MAX) )
+ {
+ mlen += sizeof (struct TALER_CRYPTO_CsRDeriveRequest);
+ rend++;
+ }
+ {
+ char obuf[mlen] GNUNET_ALIGN;
+ struct TALER_CRYPTO_BatchDeriveRequest *bdr
+ = (struct TALER_CRYPTO_BatchDeriveRequest *) obuf;
+ void *wbuf;
+
+ bdr->header.type = htons (TALER_HELPER_CS_MT_REQ_BATCH_RDERIVE);
+ bdr->header.size = htons (mlen);
+ bdr->batch_size = htonl (rend - rpos);
+ wbuf = &bdr[1];
+ for (unsigned int i = rpos; i<rend; i++)
+ {
+ struct TALER_CRYPTO_CsRDeriveRequest *rdr = wbuf;
+ const struct TALER_CRYPTO_CsDeriveRequest *cdr = &cdrs[i];
+
+ rdr->header.size = htons (sizeof (*rdr));
+ rdr->header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
+ rdr->for_melt = htonl (for_melt ? 1 : 0);
+ rdr->h_cs = *cdr->h_cs;
+ rdr->nonce = *cdr->nonce;
+ wbuf += sizeof (*rdr);
+ }
+ GNUNET_assert (wbuf == &obuf[mlen]);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending batch request [%u-%u)\n",
+ rpos,
+ rend);
+ if (GNUNET_OK !=
+ TALER_crypto_helper_send_all (dh->sock,
+ obuf,
+ sizeof (obuf)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "send");
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+ } /* end of obuf scope */
+ rpos = rend;
+ {
+ char buf[UINT16_MAX];
+ size_t off = 0;
+ const struct GNUNET_MessageHeader *hdr
+ = (const struct GNUNET_MessageHeader *) buf;
+ bool finished = false;
+
+ while (1)
+ {
+ uint16_t msize;
+ ssize_t ret;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Awaiting reply at %u (up to %u)\n",
+ wpos,
+ rend);
+ ret = recv (dh->sock,
+ &buf[off],
+ sizeof (buf) - off,
+ (finished && (0 == off))
+ ? MSG_DONTWAIT
+ : 0);
+ if (ret < 0)
+ {
+ if (EINTR == errno)
+ continue;
+ if (EAGAIN == errno)
+ {
+ GNUNET_assert (finished);
+ GNUNET_assert (0 == off);
+ break;
+ }
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "recv");
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+ if (0 == ret)
+ {
+ GNUNET_break (0 == off);
+ if (! finished)
+ return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+ if (TALER_EC_NONE == ec)
+ break;
+ return ec;
+ }
+ off += ret;
+more:
+ if (off < sizeof (struct GNUNET_MessageHeader))
+ continue;
+ msize = ntohs (hdr->size);
+ if (off < msize)
+ continue;
+ switch (ntohs (hdr->type))
+ {
+ case TALER_HELPER_CS_MT_RES_RDERIVE:
+ if (msize != sizeof (struct TALER_CRYPTO_RDeriveResponse))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ if (finished)
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ {
+ const struct TALER_CRYPTO_RDeriveResponse *rdr =
+ (const struct TALER_CRYPTO_RDeriveResponse *) buf;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %u R pair\n",
+ wpos);
+ crps[wpos] = rdr->r_pub;
+ wpos++;
+ if (wpos == rend)
+ {
+ if (TALER_EC_INVALID == ec)
+ ec = TALER_EC_NONE;
+ finished = true;
+ }
+ break;
+ }
+ case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
+ if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ {
+ const struct TALER_CRYPTO_RDeriveFailure *rdf =
+ (const struct TALER_CRYPTO_RDeriveFailure *) buf;
+
+ ec = (enum TALER_ErrorCode) ntohl (rdf->ec);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "R derivation %u failed with status %d!\n",
+ wpos,
+ ec);
+ wpos++;
+ if (wpos == rend)
+ {
+ finished = true;
+ }
+ break;
+ }
+ case TALER_HELPER_CS_MT_AVAIL:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received new key!\n");
+ if (GNUNET_OK !=
+ handle_mt_avail (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ break; /* while(1) loop ensures we recvfrom() again */
+ case TALER_HELPER_CS_MT_PURGE:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received revocation!\n");
+ if (GNUNET_OK !=
+ handle_mt_purge (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ break; /* while(1) loop ensures we recvfrom() again */
+ case TALER_HELPER_CS_SYNCED:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Synchronized add odd time with CS helper!\n");
+ dh->synced = true;
+ break;
+ default:
+ GNUNET_break_op (0);
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Received unexpected message of type %u\n",
+ ntohs (hdr->type));
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ memmove (buf,
+ &buf[msize],
+ off - msize);
+ off -= msize;
+ goto more;
+ } /* while(1) */
+ } /* scope */
+ } /* while (rpos < cdrs_length) */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Existing with %u signatures and status %d\n",
+ wpos,
+ ec);
+ return ec;
}