summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>2022-01-04 17:26:01 +0100
committerGian Demarmels <gian@demarmels.org>2022-02-04 15:33:13 +0100
commit106664ed0c50621bd20568c948ad30fccd0689ea (patch)
tree9eee0d4afe84da5c93d03360422de5daf4c90546
parent875a8b397ee4a83f1092151906ad041c4339e7b2 (diff)
downloadexchange-106664ed0c50621bd20568c948ad30fccd0689ea.tar.gz
exchange-106664ed0c50621bd20568c948ad30fccd0689ea.tar.bz2
exchange-106664ed0c50621bd20568c948ad30fccd0689ea.zip
implement TALER_CRYPTO_helper_cs_r_derive and related tests
-rw-r--r--src/include/taler_crypto_lib.h28
-rw-r--r--src/util/crypto_helper_cs.c195
-rw-r--r--src/util/taler-exchange-secmod-cs.c3
-rw-r--r--src/util/test_helper_cs.c132
4 files changed, 353 insertions, 5 deletions
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index bd889b354..a20e51204 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1800,7 +1800,7 @@ TALER_CRYPTO_helper_cs_sign (
/**
- * Ask the helper to revoke the public key associated with @param h_denom_pub .
+ * Ask the helper to revoke the public key associated with @param h_cs .
* Will cause the helper to tell all clients that the key is now unavailable,
* and to create a replacement key.
*
@@ -1812,7 +1812,7 @@ TALER_CRYPTO_helper_cs_sign (
* callback.
*
* @param dh helper to process connection
- * @param h_rsa hash of the RSA public key to revoke
+ * @param h_cs hash of the CS public key to revoke
*/
void
TALER_CRYPTO_helper_cs_revoke (
@@ -1821,6 +1821,30 @@ TALER_CRYPTO_helper_cs_revoke (
/**
+ * Ask the helper to derive R using the @param nonce and denomination key
+ * associated with @param 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[out] ec set to the error code (or #TALER_EC_NONE on success)
+ * @return R, the value inside the structure will be NULL on failure,
+ * see @a ec for details about the failure
+ */
+struct TALER_DenominationCsPublicR
+TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
+ const struct TALER_CsPubHashP *h_cs,
+ const struct TALER_WithdrawNonce *nonce,
+ enum TALER_ErrorCode *ec);
+
+
+/**
* Close connection to @a dh.
*
* @param[in] dh connection to close
diff --git a/src/util/crypto_helper_cs.c b/src/util/crypto_helper_cs.c
index 95050a1f5..5b2999348 100644
--- a/src/util/crypto_helper_cs.c
+++ b/src/util/crypto_helper_cs.c
@@ -633,6 +633,201 @@ TALER_CRYPTO_helper_cs_revoke (
}
+struct TALER_DenominationCsPublicR
+TALER_CRYPTO_helper_cs_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh,
+ const struct TALER_CsPubHashP *h_cs,
+ const struct TALER_WithdrawNonce *nonce,
+ enum TALER_ErrorCode *ec)
+{
+ struct TALER_DenominationCsPublicR r_pub;
+
+ memset (&r_pub,
+ 0,
+ sizeof (r_pub));
+
+ 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");
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ return r_pub;
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Requesting R\n");
+ {
+ struct TALER_CRYPTO_CsRDeriveRequest rdr;
+
+ rdr.header.size = htons (sizeof (rdr));
+ rdr.header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE);
+ rdr.reserved = htonl (0);
+ rdr.h_cs = *h_cs;
+ rdr.nonce = *nonce;
+ if (GNUNET_OK !=
+ TALER_crypto_helper_send_all (dh->sock,
+ &rdr,
+ sizeof (rdr)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "send");
+ do_disconnect (dh);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ return r_pub;
+ }
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Awaiting reply\n");
+ {
+ char buf[UINT16_MAX];
+ size_t off = 0;
+ const struct GNUNET_MessageHeader *hdr
+ = (const struct GNUNET_MessageHeader *) buf;
+ bool finished = false;
+
+ *ec = TALER_EC_INVALID;
+ while (1)
+ {
+ uint16_t msize;
+ ssize_t ret;
+
+ 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);
+ return r_pub;
+ }
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "recv");
+ do_disconnect (dh);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ break;
+ }
+ if (0 == ret)
+ {
+ GNUNET_break (0 == off);
+ if (! finished)
+ *ec = TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+ return r_pub;
+ }
+ 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);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ if (finished)
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ {
+ const struct TALER_CRYPTO_RDeriveResponse *rdr =
+ (const struct TALER_CRYPTO_RDeriveResponse *) buf;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received R\n");
+ *ec = TALER_EC_NONE;
+ finished = true;
+ r_pub = rdr->r_pub;
+ break;
+ }
+ case TALER_HELPER_CS_MT_RES_RDERIVE_FAILURE:
+ if (msize != sizeof (struct TALER_CRYPTO_RDeriveFailure))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ {
+ 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 failed!\n");
+ 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);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ 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);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ 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);
+ *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ memmove (buf,
+ &buf[msize],
+ off - msize);
+ off -= msize;
+ goto more;
+ } /* while(1) */
+end:
+ return r_pub;
+ }
+}
+
+
void
TALER_CRYPTO_helper_cs_disconnect (
struct TALER_CRYPTO_CsDenominationHelper *dh)
diff --git a/src/util/taler-exchange-secmod-cs.c b/src/util/taler-exchange-secmod-cs.c
index 14f0a5d10..0df7c3ddf 100644
--- a/src/util/taler-exchange-secmod-cs.c
+++ b/src/util/taler-exchange-secmod-cs.c
@@ -618,7 +618,6 @@ handle_r_derive_request (struct TES_Client *client,
&rdf.header);
}
- // TODO: print nonce too?
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received request to derive R with key %s\n",
GNUNET_h2s (&rdr->h_cs.hash));
@@ -692,7 +691,7 @@ cs_work_dispatch (struct TES_Client *client,
return handle_revoke_request (
client,
(const struct TALER_CRYPTO_CsRevokeRequest *) hdr);
- case TALER_HELPER_CS_MT_RES_RDERIVE:
+ case TALER_HELPER_CS_MT_REQ_RDERIVE:
if (msize != sizeof (struct TALER_CRYPTO_CsRDeriveRequest))
{
GNUNET_break_op (0);
diff --git a/src/util/test_helper_cs.c b/src/util/test_helper_cs.c
index 41d363fdc..d59c21637 100644
--- a/src/util/test_helper_cs.c
+++ b/src/util/test_helper_cs.c
@@ -256,6 +256,133 @@ test_revocation (struct TALER_CRYPTO_CsDenominationHelper *dh)
/**
+ * Test R derivation logic.
+ *
+ * @param dh handle to the helper
+ * @return 0 on success
+ */
+static int
+test_r_derive (struct TALER_CRYPTO_CsDenominationHelper *dh)
+{
+ struct TALER_DenominationCsPublicR r_pub;
+ enum TALER_ErrorCode ec;
+ bool success = false;
+ struct TALER_PlanchetSecretsP ps;
+ struct TALER_CoinPubHash c_hash;
+
+ TALER_planchet_setup_random (&ps, TALER_DENOMINATION_RSA);
+ for (unsigned int i = 0; i<MAX_KEYS; i++)
+ {
+ if (! keys[i].valid)
+ continue;
+ // TODO: insert assertion into other checks
+ GNUNET_assert (TALER_DENOMINATION_CS == keys[i].denom_pub.cipher);
+ {
+ struct TALER_PlanchetDetail pd;
+ pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
+
+ TALER_cs_withdraw_nonce_derive (&ps.coin_priv,
+ &pd.blinded_planchet.details.
+ cs_blinded_planchet.nonce);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Requesting R derivation with key %s\n",
+ GNUNET_h2s (&keys[i].h_cs.hash));
+ r_pub = TALER_CRYPTO_helper_cs_r_derive (dh,
+ &keys[i].h_cs,
+ &pd.blinded_planchet.details.
+ cs_blinded_planchet.nonce,
+ &ec);
+ }
+ switch (ec)
+ {
+ case TALER_EC_NONE:
+ if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_remaining (
+ keys[i].start_time.abs_time),
+ >,
+ GNUNET_TIME_UNIT_SECONDS))
+ {
+ /* key worked too early */
+ GNUNET_break (0);
+ return 4;
+ }
+ if (GNUNET_TIME_relative_cmp (GNUNET_TIME_absolute_get_duration (
+ keys[i].start_time.abs_time),
+ >,
+ keys[i].validity_duration))
+ {
+ /* key worked too later */
+ GNUNET_break (0);
+ return 5;
+ }
+
+ // since R is part of the signature creation process, it can't be tested fully here
+ // instead it will be further tested in the signature creation process
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received valid R for key %s\n",
+ GNUNET_h2s (&keys[i].h_cs.hash));
+ success = true;
+ break;
+ case TALER_EC_EXCHANGE_DENOMINATION_HELPER_TOO_EARLY:
+ /* This 'failure' is expected, we're testing also for the
+ error handling! */
+ if ( (GNUNET_TIME_relative_is_zero (
+ GNUNET_TIME_absolute_get_remaining (
+ keys[i].start_time.abs_time))) &&
+ (GNUNET_TIME_relative_cmp (
+ GNUNET_TIME_absolute_get_duration (
+ keys[i].start_time.abs_time),
+ <,
+ keys[i].validity_duration)) )
+ {
+ /* key should have worked! */
+ GNUNET_break (0);
+ return 6;
+ }
+ break;
+ default:
+ /* unexpected error */
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unexpected error %d\n",
+ ec);
+ return 7;
+ }
+ }
+ if (! success)
+ {
+ /* no valid key for signing found, also bad */
+ GNUNET_break (0);
+ return 16;
+ }
+
+ /* check R derivation does not work if the key is unknown */
+ {
+ struct TALER_CsPubHashP rnd;
+ struct TALER_WithdrawNonce nonce;
+
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ &rnd,
+ sizeof (rnd));
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ &nonce,
+ sizeof (nonce));
+ r_pub = TALER_CRYPTO_helper_cs_r_derive (dh,
+ &rnd,
+ &nonce,
+ &ec);
+ if (TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN != ec)
+ {
+ GNUNET_break (0);
+ return 17;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "R derivation with invalid key %s failed as desired\n",
+ GNUNET_h2s (&rnd.hash));
+ }
+ return 0;
+}
+
+
+/**
* Test signing logic.
*
* @param dh handle to the helper
@@ -600,9 +727,11 @@ run_test (void)
" Done (%u keys)\n",
num_keys);
ret = 0;
- // TODO: implement other tests
if (0 == ret)
ret = test_revocation (dh);
+ if (0 == ret)
+ ret = test_r_derive (dh);
+ // TODO: implement other tests
// if (0 == ret)
// ret = test_signing (dh);
// if (0 == ret)
@@ -685,6 +814,7 @@ main (int argc,
(int) code);
ret = 5;
}
+ // TODO: remove
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"I am here");
GNUNET_OS_process_destroy (helper);