[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-donau] 01/02: [secmod/helpers] Add helpers from Exchange and adap
From: |
gnunet |
Subject: |
[taler-donau] 01/02: [secmod/helpers] Add helpers from Exchange and adapt to Donau |
Date: |
Sun, 14 Jan 2024 22:56:53 +0100 |
This is an automated email from the git hooks/post-receive script.
pius-loosli pushed a commit to branch master
in repository donau.
commit ade143d8dcda67578aa3d8479b5ab45fd69303d7
Author: Pius Loosli <loosp2@bfh.ch>
AuthorDate: Sun Jan 14 22:41:57 2024 +0100
[secmod/helpers] Add helpers from Exchange and adapt to Donau
---
src/include/donau_crypto_lib.h | 565 ++++++++++++++++-
src/util/Makefile.am | 5 +-
src/util/crypto_helper_common.c | 51 ++
src/util/crypto_helper_common.h | 41 ++
src/util/crypto_helper_cs.c | 1317 +++++++++++++++++++++++++++++++++++++++
src/util/crypto_helper_esign.c | 557 +++++++++++++++++
src/util/crypto_helper_rsa.c | 917 +++++++++++++++++++++++++++
7 files changed, 3443 insertions(+), 10 deletions(-)
diff --git a/src/include/donau_crypto_lib.h b/src/include/donau_crypto_lib.h
index 2616a9e..ad7f950 100644
--- a/src/include/donau_crypto_lib.h
+++ b/src/include/donau_crypto_lib.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2023 Taler Systems SA
+ Copyright (C) 2023-2024 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
@@ -21,6 +21,7 @@
* @author Christian Grothoff <christian@grothoff.org>
* @author Özgür Kesim <oec-taler@kesim.org>
* @author Lukas Matyja
+ * @author Pius Loosli
*/
#if ! defined (__DONAU_UTIL_LIB_H_INSIDE__)
#error "Only <donau_util.h> can be included directly."
@@ -126,8 +127,10 @@ struct DONAU_DonationUnitHashP
* @return 0 if the keys are equal, otherwise -1 or 1
*/
int
-DONAU_donation_unit_pub_cmp (const struct DONAU_DonationUnitPublicKey
*donation_unit1,
- const struct DONAU_DonationUnitPublicKey *donation_unit2);
+DONAU_donation_unit_pub_cmp (const struct
+ DONAU_DonationUnitPublicKey *donation_unit1,
+ const struct
+ DONAU_DonationUnitPublicKey *donation_unit2);
/**
* Make a (deep) copy of the given @a donation_unit_src to
@@ -137,8 +140,12 @@ DONAU_donation_unit_pub_cmp (const struct
DONAU_DonationUnitPublicKey *donation_
* @param donation_unit_src public key to copy
*/
void
-DONAU_donation_unit_pub_deep_copy (struct DONAU_DonationUnitPublicKey
*donation_unit_dst,
- const struct DONAU_DonationUnitPublicKey
*donation_unit_src);
+DONAU_donation_unit_pub_deep_copy (struct
+ DONAU_DonationUnitPublicKey *
+ donation_unit_dst,
+ const struct
+ DONAU_DonationUnitPublicKey *
+ donation_unit_src);
/**
* Free internals of @a donation_unit_pub, but not @a donation_unit_pub itself.
@@ -146,7 +153,8 @@ DONAU_donation_unit_pub_deep_copy (struct
DONAU_DonationUnitPublicKey *donation_
* @param[in] donation_unit_pub key to free
*/
void
-DONAU_donation_unit_pub_free (struct DONAU_DonationUnitPublicKey
*donation_unit_pub);
+DONAU_donation_unit_pub_free (struct
+ DONAU_DonationUnitPublicKey *donation_unit_pub);
/**
* Hash used to represent a Donation Receipt
@@ -174,9 +182,9 @@ struct DONAU_HashDonorTaxId
struct DONAU_BlindedDonationUnitSignature
{
/**
- * The blinded signature
+ * Donation Units use blind signatures.
*/
- struct TALER_DenominationSignature b_sig;
+ struct GNUNET_CRYPTO_BlindedSignature *blinded_sig;
};
@@ -324,9 +332,134 @@ DONAU_donation_statement_verify (
const struct DONAU_DonauSignatureP *statement_sig);
-/* ********************* helper ************************** */
+///* ********************* donau blind signing ************************** */
+/**
+ * Free internals of @a donation_unit_sig, but not @a donation_unit_sig itself.
+ *
+ * @param[in] donation_unit_sig signature to free
+// */
+void
+DONAU_blinded_donation_unit_sig_free (
+ struct DONAU_BlindedDonationUnitSignature *donation_unit_sig);
+
+// FIXME: Copied from taler_crypto_lib.h, is anything of this necessary?
+///**
+// * Compute the hash of the given @a donation_unit_pub.
+// *
+// * @param donation_unit_pub public key to hash
+// * @param[out] donation_unit_hash resulting hash value
+// */
+// void
+// TALER_donation_unit_pub_hash (const struct DONAU_DonationUnitPublicKey
*donation_unit_pub,
+// struct DONAU_DonationUnitHashP *donation_unit_hash);
+//
+//
+///**
+// * Make a (deep) copy of the given @a donation_unit_src to
+// * @a donation_unit_dst.
+// *
+// * @param[out] donation_unit_dst target to copy to
+// * @param donation_unit_src public key to copy
+// */
+// void
+// TALER_donation_unit_pub_deep_copy (struct DONAU_DonationUnitPublicKey
*donation_unit_dst,
+// const struct DONAU_DonationUnitPublicKey
*donation_unit_src);
+//
+//
+///**
+// * Make a (deep) copy of the given @a donation_unit_src to
+// * @a donation_unit_dst.
+// *
+// * @param[out] donation_unit_dst target to copy to
+// * @param donation_unit_src public key to copy
+// */
+// void
+// TALER_donation_unit_sig_deep_copy (struct DONAU_DonationUnitSignature
*donation_unit_dst,
+// const struct DONAU_DonationUnitSignature
*donation_unit_src);
+//
+//
+///**
+// * Make a (deep) copy of the given @a donation_unit_src to
+// * @a donation_unit_dst.
+// *
+// * @param[out] donation_unit_dst target to copy to
+// * @param donation_unit_src public key to copy
+// */
+// void
+// TALER_blinded_donation_unit_sig_deep_copy (
+// struct DONAU_BlindedDonationUnitSignature *donation_unit_dst,
+// const struct DONAU_BlindedDonationUnitSignature *donation_unit_src);
+//
+//
+///**
+// * Compare two donation unit public keys.
+// *
+// * @param donation_unit1 first key
+// * @param donation_unit2 second key
+// * @return 0 if the keys are equal, otherwise -1 or 1
+// */
+// int
+// TALER_donation_unit_pub_cmp (const struct DONAU_DonationUnitPublicKey
*donation_unit1,
+// const struct DONAU_DonationUnitPublicKey
*donation_unit2);
+//
+//
+///**
+// * Compare two donation unit signatures.
+// *
+// * @param sig1 first signature
+// * @param sig2 second signature
+// * @return 0 if the keys are equal, otherwise -1 or 1
+// */
+// int
+// TALER_donation_unit_sig_cmp (const struct DONAU_DonationUnitSignature *sig1,
+// const struct DONAU_DonationUnitSignature *sig2);
+//
+//
+///**
+// * Compare two blinded donation unit signatures.
+// *
+// * @param sig1 first signature
+// * @param sig2 second signature
+// * @return 0 if the keys are equal, otherwise -1 or 1
+// */
+// int
+// TALER_blinded_donation_unit_sig_cmp (
+// const struct DONAU_BlindedDonationUnitSignature *sig1,
+// const struct DONAU_BlindedDonationUnitSignature *sig2);
+//
+//
+///**
+// * Compare two blinded planchets.
+// *
+// * @param bp1 first blinded planchet
+// * @param bp2 second blinded planchet
+// * @return 0 if the keys are equal, otherwise -1 or 1
+// */
+// int
+// TALER_blinded_planchet_cmp (
+// const struct DONAU_BlindedPlanchet *bp1,
+// const struct DONAU_BlindedPlanchet *bp2);
+//
+//
+///**
+// * Verify signature made with a donation unit public key
+// * over a donation receipt.
+// *
+// * @param donation_unit_pub public donation unit key
+// * @param donation_unit_sig signature made with the private key
+// * @param c_hash hash over the coin
+// * @return #GNUNET_OK if the signature is valid
+// */
+// enum GNUNET_GenericReturnValue
+// TALER_donation_unit_pub_verify (const struct DONAU_DonationUnitPublicKey
*donation_unit_pub,
+// const struct DONAU_DonationUnitSignature
*donation_unit_sig,
+// const struct DONAU_ *c_hash);
+//
+
+
+/*********************** helpers
************************************************/
/**
* Group of donation units. These are the common fields of an array of
* donation units.
@@ -369,4 +502,418 @@ struct TALER_DonauBatchIssueValues
};
+/* ********************* Helper-based RSA operations
************************** */
+/**
+ * Function called with information about available keys for signing. Usually
+ * only called once per key upon connect. Also called again in case a key is
+ * being revoked, in that case with an @a end_time of zero.
+ *
+ * @param cls closure
+ * @param section_name name of the donation unit type in the configuration;
+ * NULL if the key has been revoked or purged
+ * @param start_time when does the key become available for signing;
+ * zero if the key has been revoked or purged
+ * @param validity_duration how long does the key remain available for signing;
+ * zero if the key has been revoked or purged
+ * @param h_rsa hash of the RSA @a donation_unit_pub that is available (or was
purged)
+ * @param bs_pub the public key itself, NULL if the key was revoked or purged
+ * @param sm_pub public key of the security module, NULL if the key was
revoked or purged
+ * @param sm_sig signature from the security module, NULL if the key was
revoked or purged
+ * The signature was already verified against @a sm_pub.
+ */
+typedef void
+(*DONAU_CRYPTO_RsaDonationUnitKeyStatusCallback)(
+ void *cls,
+ const char *section_name,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Relative validity_duration,
+ const struct TALER_RsaPubHashP *h_rsa,
+ struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
+ const struct TALER_SecurityModulePublicKeyP *sm_pub,
+ const struct TALER_SecurityModuleSignatureP *sm_sig);
+
+/**
+ * Handle for talking to an Donation unit key signing helper.
+ */
+struct DONAU_CRYPTO_RsaDonationUnitHelper;
+
+
+/**
+ * Initiate connection to an donation unit key helper.
+ *
+ * @param cfg configuration to use
+ * @param section configuration section prefix to use, usually 'taler' or
'donau'
+ * @param dkc function to call with key information
+ * @param dkc_cls closure for @a dkc
+ * @return NULL on error (such as bad @a cfg).
+ */
+struct DONAU_CRYPTO_RsaDonationUnitHelper *
+DONAU_CRYPTO_helper_rsa_connect (
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ DONAU_CRYPTO_RsaDonationUnitKeyStatusCallback dkc,
+ void *dkc_cls);
+
+
+/**
+ * Function to call to 'poll' for updates to the available key material.
+ * Should be called whenever it is important that the key material status is
+ * current, like when handling a "/keys" request. This function basically
+ * briefly checks if there are messages from the helper announcing changes to
+ * donation unit keys.
+ *
+ * @param dh helper process connection
+ */
+void
+DONAU_CRYPTO_helper_rsa_poll (struct DONAU_CRYPTO_RsaDonationUnitHelper *dh);
+
+/**
+ * Close connection to @a dh.
+ *
+ * @param[in] dh connection to close
+ */
+void
+DONAU_CRYPTO_helper_rsa_disconnect (
+ struct DONAU_CRYPTO_RsaDonationUnitHelper *dh);
+
+
+/* **************** Helper-based CS operations **************** */
+
+/**
+ * Handle for talking to an DonationUnit key signing helper.
+ */
+struct DONAU_CRYPTO_CsDonationUnitHelper;
+
+/**
+ * Function called with information about available keys for signing. Usually
+ * only called once per key upon connect. Also called again in case a key is
+ * being revoked, in that case with an @a end_time of zero.
+ *
+ * @param cls closure
+ * @param section_name name of the donation unit type in the configuration;
+ * NULL if the key has been revoked or purged
+ * @param start_time when does the key become available for signing;
+ * zero if the key has been revoked or purged
+ * @param validity_duration how long does the key remain available for signing;
+ * zero if the key has been revoked or purged
+ * @param h_cs hash of the CS @a donation_unit_pub that is available (or was
purged)
+ * @param bsign_pub the public key itself, NULL if the key was revoked or
purged
+ * @param sm_pub public key of the security module, NULL if the key was
revoked or purged
+ * @param sm_sig signature from the security module, NULL if the key was
revoked or purged
+ * The signature was already verified against @a sm_pub.
+ */
+typedef void
+(*DONAU_CRYPTO_CsDonationUnitKeyStatusCallback)(
+ void *cls,
+ const char *section_name,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Relative validity_duration,
+ const struct TALER_CsPubHashP *h_cs,
+ struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub,
+ const struct TALER_SecurityModulePublicKeyP *sm_pub,
+ const struct TALER_SecurityModuleSignatureP *sm_sig);
+
+
+/**
+ * Initiate connection to an donation unit key helper.
+ *
+ * @param cfg configuration to use
+ * @param section configuration section prefix to use, usually 'taler' or
'donau'
+ * @param dkc function to call with key information
+ * @param dkc_cls closure for @a dkc
+ * @return NULL on error (such as bad @a cfg).
+ */
+struct DONAU_CRYPTO_CsDonationUnitHelper *
+DONAU_CRYPTO_helper_cs_connect (
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ DONAU_CRYPTO_CsDonationUnitKeyStatusCallback dkc,
+ void *dkc_cls);
+
+
+/**
+ * Function to call to 'poll' for updates to the available key material.
+ * Should be called whenever it is important that the key material status is
+ * current, like when handling a "/keys" request. This function basically
+ * briefly checks if there are messages from the helper announcing changes to
+ * donation unit keys.
+ *
+ * @param dh helper process connection
+ */
+void
+DONAU_CRYPTO_helper_cs_poll (struct DONAU_CRYPTO_CsDonationUnitHelper *dh);
+
+
+/**
+ * Request helper @a dh to sign @a req.
+ *
+ * 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 req information about the key to sign with and the value to sign
+ * @param for_melt true if for melt operation
+ * @param[out] bs set to the blind signature
+ * @return #TALER_EC_NONE on success
+ */
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_cs_sign (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ const struct TALER_CRYPTO_CsSignRequest *req,
+ bool for_melt,
+ struct DONAU_BlindedDonationUnitSignature *bs);
+
+
+/**
+ * Request helper @a dh to sign batch of @a reqs requests.
+ *
+ * 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 reqs information about the keys to sign with and the values to sign
+ * @param reqs_length length of the @a reqs array
+ * @param for_melt true if this is for a melt operation
+ * @param[out] bss array set to the blind signatures, must be of length @a
reqs_length!
+ * @return #TALER_EC_NONE on success
+ */
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_cs_batch_sign (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ unsigned int reqs_length,
+ const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
+ bool for_melt,
+ struct DONAU_BlindedDonationUnitSignature bss[static reqs_length]);
+
+
+/**
+ * Ask the helper to revoke the public key associated with @a h_cs.
+ * Will cause the helper to tell all clients that the key is now unavailable,
+ * and to create a replacement key.
+ *
+ * This operation will block until the revocation request has been
+ * transmitted. Should this process receive a signal (that is not ignored)
+ * while the operation is pending, the operation may fail. If the key is
+ * unknown, this function will also appear to have succeeded. To be sure that
+ * the revocation worked, clients must watch the donation unit key status
+ * callback.
+ *
+ * @param dh helper to process connection
+ * @param h_cs hash of the CS public key to revoke
+ */
+void
+DONAU_CRYPTO_helper_cs_revoke (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ const struct TALER_CsPubHashP *h_cs);
+
+
+/**
+ * Ask the helper to derive R using the information
+ * from @a cdr.
+ *
+ * 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 cdr derivation input data
+ * @param for_melt true if this is for a melt operation
+ * @param[out] crp set to the pair of R values
+ * @return set to the error code (or #TALER_EC_NONE on success)
+ */
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_cs_r_derive (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ const struct TALER_CRYPTO_CsDeriveRequest *cdr,
+ bool for_melt,
+ struct GNUNET_CRYPTO_CSPublicRPairP *crp);
+
+
+/**
+ * Ask the helper to derive R using the information from @a cdrs.
+ *
+ * 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 cdrs_length length of the @a cdrs array
+ * @param cdrs array with derivation input data
+ * @param for_melt true if this is for a melt operation
+ * @param[out] crps array set to the pair of R values, must be of length @a
cdrs_length
+ * @return set to the error code (or #TALER_EC_NONE on success)
+ */
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_cs_r_batch_derive (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ unsigned int cdrs_length,
+ const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
+ bool for_melt,
+ struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length]);
+
+
+/**
+ * Close connection to @a dh.
+ *
+ * @param[in] dh connection to close
+ */
+void
+DONAU_CRYPTO_helper_cs_disconnect (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh);
+
+
+/*********************** Helper-based EDDSA operations
*****************************/
+
+/**
+ * Handle for talking to an online key signing helper.
+ */
+struct DONAU_CRYPTO_DonauSignHelper;
+
+/**
+ * Function called with information about available keys for signing. Usually
+ * only called once per key upon connect. Also called again in case a key is
+ * being revoked, in that case with an @a end_time of zero.
+ *
+ * @param cls closure
+ * @param start_time when does the key become available for signing;
+ * zero if the key has been revoked or purged
+ * @param validity_duration how long does the key remain available for signing;
+ * zero if the key has been revoked or purged
+ * @param exchange_pub the public key itself, NULL if the key was revoked or
purged
+ * @param sm_pub public key of the security module, NULL if the key was
revoked or purged
+ * @param sm_sig signature from the security module, NULL if the key was
revoked or purged
+ * The signature was already verified against @a sm_pub.
+ */
+typedef void
+(*DONAU_CRYPTO_DonauKeyStatusCallback)(
+ void *cls,
+ struct GNUNET_TIME_Timestamp start_time,
+ struct GNUNET_TIME_Relative validity_duration,
+ const struct DONAU_DonauPublicKeyP *exchange_pub,
+ const struct TALER_SecurityModulePublicKeyP *sm_pub,
+ const struct TALER_SecurityModuleSignatureP *sm_sig);
+
+
+/**
+ * Initiate connection to an online signing key helper.
+ *
+ * @param cfg configuration to use
+ * @param section configuration section prefix to use, usually 'taler' or
'donau'
+ * @param ekc function to call with key information
+ * @param ekc_cls closure for @a ekc
+ * @return NULL on error (such as bad @a cfg).
+ */
+struct DONAU_CRYPTO_DonauSignHelper *
+DONAU_CRYPTO_helper_esign_connect (
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ DONAU_CRYPTO_DonauKeyStatusCallback ekc,
+ void *ekc_cls);
+
+
+/**
+ * Function to call to 'poll' for updates to the available key material.
+ * Should be called whenever it is important that the key material status is
+ * current, like when handling a "/keys" request. This function basically
+ * briefly checks if there are messages from the helper announcing changes to
+ * donau online signing keys.
+ *
+ * @param esh helper process connection
+ */
+void
+DONAU_CRYPTO_helper_esign_poll (struct DONAU_CRYPTO_DonauSignHelper *esh);
+
+
+/**
+ * Request helper @a esh to sign @a msg using the current online
+ * signing key.
+ *
+ * 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 esh helper process connection
+ * @param purpose message to sign (must extend beyond the purpose)
+ * @param[out] donau_pub set to the public key used for the signature upon
success
+ * @param[out] donau_sig set to the signature upon success
+ * @return the error code (or #TALER_EC_NONE on success)
+ */
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_esign_sign_ (
+ struct DONAU_CRYPTO_DonauSignHelper *esh,
+ const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+ struct DONAU_DonauPublicKeyP *donau_pub,
+ struct DONAU_DonauSignatureP *donau_sig);
+
+
+/**
+ * Request helper @a esh to sign @a msg using the current online
+ * signing key.
+ *
+ * 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 esh helper process connection
+ * @param ps message to sign (MUST begin with a purpose)
+ * @param[out] epub set to the public key used for the signature upon success
+ * @param[out] esig set to the signature upon success
+ * @return the error code (or #TALER_EC_NONE on success)
+ */
+#define DONAU_CRYPTO_helper_esign_sign(esh,ps,epub,esig) ( \
+ /* check size is set correctly */ \
+ GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*ps)), \
+ /* check 'ps' begins with the purpose */ \
+ GNUNET_static_assert (((void*) (ps)) == \
+ ((void*) &(ps)->purpose)), \
+ DONAU_CRYPTO_helper_esign_sign_ (esh, \
+ &(ps)->purpose, \
+ epub, \
+ esig) )
+
+
+/**
+ * Ask the helper to revoke the public key @a donau_pub .
+ * Will cause the helper to tell all clients that the key is now unavailable,
+ * and to create a replacement key.
+ *
+ * This operation will block until the revocation request has been
+ * transmitted. Should this process receive a signal (that is not ignored)
+ * while the operation is pending, the operation may fail. If the key is
+ * unknown, this function will also appear to have succeeded. To be sure that
+ * the revocation worked, clients must watch the signing key status callback.
+ *
+ * @param esh helper to process connection
+ * @param donau_pub the public key to revoke
+ */
+void
+DONAU_CRYPTO_helper_esign_revoke (
+ struct DONAU_CRYPTO_DonauSignHelper *esh,
+ const struct DONAU_DonauPublicKeyP *donau_pub);
+
+
+/**
+ * Close connection to @a esh.
+ *
+ * @param[in] esh connection to close
+ */
+void
+DONAU_CRYPTO_helper_esign_disconnect (
+ struct DONAU_CRYPTO_DonauSignHelper *esh);
+
+
#endif
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 92f00ac..889249e 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -15,7 +15,10 @@ lib_LTLIBRARIES = \
libdonauutil_la_SOURCES = \
charity_signatures.c \
donau_signatures.c \
- donau_os_installation.c
+ donau_os_installation.c \
+ crypto_helper_cs.c \
+ crypto_helper_rsa.c \
+ crypto_helper_esign.c
libdonauutil_la_LIBADD = \
-ltalerutil \
diff --git a/src/util/crypto_helper_common.c b/src/util/crypto_helper_common.c
new file mode 100644
index 0000000..fccfe9b
--- /dev/null
+++ b/src/util/crypto_helper_common.c
@@ -0,0 +1,51 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2020, 2021 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
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file util/crypto_helper_common.c
+ * @brief Common functions for the exchange security modules
+ * @author Florian Dold <dold@taler.net>
+ */
+#include <taler/platform.h>
+#include <taler/taler_util.h>
+#include <taler/taler_signatures.h>
+
+
+enum GNUNET_GenericReturnValue
+TALER_crypto_helper_send_all (int sock,
+ const void *buf,
+ size_t buf_size)
+{
+ size_t off = 0;
+
+ while (off < buf_size)
+ {
+ ssize_t ret;
+
+ ret = send (sock,
+ buf + off,
+ buf_size - off,
+ 0);
+ if (ret < 0)
+ {
+ if (EINTR == errno)
+ continue;
+ return GNUNET_SYSERR;
+ }
+ GNUNET_assert (ret > 0);
+ off += ret;
+ }
+ return GNUNET_OK;
+}
diff --git a/src/util/crypto_helper_common.h b/src/util/crypto_helper_common.h
new file mode 100644
index 0000000..cf8b281
--- /dev/null
+++ b/src/util/crypto_helper_common.h
@@ -0,0 +1,41 @@
+/*
+ This file is part of GNU Taler
+ Copyright (C) 2021 Taler Systems SA
+
+ GNU 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
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see
+ <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file util/crypto_helper_common.h
+ * @brief Common functions for the exchange security modules
+ * @author Florian Dold <dold@taler.net>
+ */
+#ifndef CRYPTO_HELPER_COMMON_H
+#define CRYPTO_HELPER_COMMON_H
+
+#include <gnunet/gnunet_util_lib.h>
+#include <gnunet/gnunet_network_lib.h>
+
+/**
+ * Send all @a buf_size bytes from @a buf to @a sock.
+ *
+ * @param sock socket to send on
+ * @param buf data to send
+ * @param buf_size number of bytes in @a buf
+ * @return #GNUNET_OK on success
+ */
+enum GNUNET_GenericReturnValue
+TALER_crypto_helper_send_all (int sock,
+ const void *buf,
+ size_t buf_size);
+
+#endif
diff --git a/src/util/crypto_helper_cs.c b/src/util/crypto_helper_cs.c
new file mode 100644
index 0000000..fd04663
--- /dev/null
+++ b/src/util/crypto_helper_cs.c
@@ -0,0 +1,1317 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2020-2024 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
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file util/crypto_helper_cs.c
+ * @brief utility functions for running out-of-process private key operations
+ * @author Christian Grothoff
+ * @author Pius Loosli
+ */
+#include "taler/platform.h"
+#include "taler/taler_util.h"
+#include "taler/taler_signatures.h"
+#include "taler/taler-exchange-secmod-cs.h"
+#include <poll.h>
+#include "crypto_helper_common.h"
+#include "donau_util.h"
+
+struct DONAU_CRYPTO_CsDonationUnitHelper
+{
+ /**
+ * Function to call with updates to available key material.
+ */
+ DONAU_CRYPTO_CsDonationUnitKeyStatusCallback dkc;
+
+ /**
+ * Closure for @e dkc
+ */
+ void *dkc_cls;
+
+ /**
+ * Socket address of the donation unit helper process.
+ * Used to reconnect if the connection breaks.
+ */
+ struct sockaddr_un sa;
+
+ /**
+ * The UNIX domain socket, -1 if we are currently not connected.
+ */
+ int sock;
+
+ /**
+ * Have we ever been sync'ed?
+ */
+ bool synced;
+};
+
+
+/**
+ * Disconnect from the helper process. Updates
+ * @e sock field in @a dh.
+ *
+ * @param[in,out] dh handle to tear down connection of
+ */
+static void
+do_disconnect (struct DONAU_CRYPTO_CsDonationUnitHelper *dh)
+{
+ GNUNET_break (0 == close (dh->sock));
+ dh->sock = -1;
+ dh->synced = false;
+}
+
+
+/**
+ * Try to connect to the helper process. Updates
+ * @e sock field in @a dh.
+ *
+ * @param[in,out] dh handle to establish connection for
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+try_connect (struct DONAU_CRYPTO_CsDonationUnitHelper *dh)
+{
+ if (-1 != dh->sock)
+ return GNUNET_OK;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Establishing connection!\n");
+ dh->sock = socket (AF_UNIX,
+ SOCK_STREAM,
+ 0);
+ if (-1 == dh->sock)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "socket");
+ return GNUNET_SYSERR;
+ }
+ if (0 !=
+ connect (dh->sock,
+ (const struct sockaddr *) &dh->sa,
+ sizeof (dh->sa)))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "connect",
+ dh->sa.sun_path);
+ do_disconnect (dh);
+ return GNUNET_SYSERR;
+ }
+ DONAU_CRYPTO_helper_cs_poll (dh);
+ return GNUNET_OK;
+}
+
+
+struct DONAU_CRYPTO_CsDonationUnitHelper *
+DONAU_CRYPTO_helper_cs_connect (
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ DONAU_CRYPTO_CsDonationUnitKeyStatusCallback dkc,
+ void *dkc_cls)
+{
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh;
+ char *unixpath;
+ char *secname;
+
+ GNUNET_asprintf (&secname,
+ "%s-exchange-secmod-cs",
+ section);
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ secname,
+ "UNIXPATH",
+ &unixpath))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ secname,
+ "UNIXPATH");
+ GNUNET_free (secname);
+ return NULL;
+ }
+ /* we use >= here because we want the sun_path to always
+ be 0-terminated */
+ if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ secname,
+ "UNIXPATH",
+ "path too long");
+ GNUNET_free (unixpath);
+ GNUNET_free (secname);
+ return NULL;
+ }
+ GNUNET_free (secname);
+ dh = GNUNET_new (struct DONAU_CRYPTO_CsDonationUnitHelper);
+ dh->dkc = dkc;
+ dh->dkc_cls = dkc_cls;
+ dh->sa.sun_family = AF_UNIX;
+ strncpy (dh->sa.sun_path,
+ unixpath,
+ sizeof (dh->sa.sun_path) - 1);
+ GNUNET_free (unixpath);
+ dh->sock = -1;
+ if (GNUNET_OK !=
+ try_connect (dh))
+ {
+ DONAU_CRYPTO_helper_cs_disconnect (dh);
+ return NULL;
+ }
+ return dh;
+}
+
+
+/**
+ * Handle a #DONAU_HELPER_CS_MT_AVAIL message from the helper.
+ *
+ * @param dh helper context
+ * @param hdr message that we received
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+handle_mt_avail (struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ const struct TALER_CRYPTO_CsKeyAvailableNotification *kan
+ = (const struct TALER_CRYPTO_CsKeyAvailableNotification *) hdr;
+ const char *buf = (const char *) &kan[1];
+ const char *section_name;
+ uint16_t snl;
+
+ if (sizeof (*kan) > ntohs (hdr->size))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ snl = ntohs (kan->section_name_len);
+ if (ntohs (hdr->size) != sizeof (*kan) + snl)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (0 == snl)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ section_name = buf;
+ if ('\0' != section_name[snl - 1])
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ {
+ struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub;
+ struct TALER_CsPubHashP h_cs;
+
+ 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;
+
+ 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),
+ section_name);
+ if (GNUNET_OK !=
+ TALER_exchange_secmod_cs_verify (
+ &h_cs,
+ section_name,
+ GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
+ GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
+ &kan->secm_pub,
+ &kan->secm_sig))
+ {
+ GNUNET_break_op (0);
+ GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
+ return GNUNET_SYSERR;
+ }
+ dh->dkc (dh->dkc_cls,
+ section_name,
+ GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
+ GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
+ &h_cs,
+ bsign_pub,
+ &kan->secm_pub,
+ &kan->secm_sig);
+ GNUNET_CRYPTO_blind_sign_pub_decref (bsign_pub);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle a #DONAU_HELPER_CS_MT_PURGE message from the helper.
+ *
+ * @param dh helper context
+ * @param hdr message that we received
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+handle_mt_purge (struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ const struct TALER_CRYPTO_CsKeyPurgeNotification *pn
+ = (const struct TALER_CRYPTO_CsKeyPurgeNotification *) hdr;
+
+ if (sizeof (*pn) != ntohs (hdr->size))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received revocation of donation unit key %s\n",
+ GNUNET_h2s (&pn->h_cs.hash));
+ dh->dkc (dh->dkc_cls,
+ NULL,
+ GNUNET_TIME_UNIT_ZERO_TS,
+ GNUNET_TIME_UNIT_ZERO,
+ &pn->h_cs,
+ NULL,
+ NULL,
+ NULL);
+ return GNUNET_OK;
+}
+
+
+void
+DONAU_CRYPTO_helper_cs_poll (struct DONAU_CRYPTO_CsDonationUnitHelper *dh)
+{
+ char buf[UINT16_MAX];
+ size_t off = 0;
+ unsigned int retry_limit = 3;
+ const struct GNUNET_MessageHeader *hdr
+ = (const struct GNUNET_MessageHeader *) buf;
+
+ if (GNUNET_OK !=
+ try_connect (dh))
+ return; /* give up */
+ while (1)
+ {
+ uint16_t msize;
+ ssize_t ret;
+
+ ret = recv (dh->sock,
+ buf + off,
+ sizeof (buf) - off,
+ (dh->synced && (0 == off))
+ ? MSG_DONTWAIT
+ : 0);
+ if (ret < 0)
+ {
+ if (EINTR == errno)
+ continue;
+ if (EAGAIN == errno)
+ {
+ GNUNET_assert (dh->synced);
+ GNUNET_assert (0 == off);
+ break;
+ }
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "recv");
+ do_disconnect (dh);
+ if (0 == retry_limit)
+ return; /* give up */
+ if (GNUNET_OK !=
+ try_connect (dh))
+ return; /* give up */
+ retry_limit--;
+ continue;
+ }
+ if (0 == ret)
+ {
+ GNUNET_break (0 == off);
+ return;
+ }
+ off += ret;
+more:
+ if (off < sizeof (struct GNUNET_MessageHeader))
+ continue;
+ msize = ntohs (hdr->size);
+ if (off < msize)
+ continue;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received message of type %u and length %u\n",
+ (unsigned int) ntohs (hdr->type),
+ (unsigned int) msize);
+ switch (ntohs (hdr->type))
+ {
+ case TALER_HELPER_CS_MT_AVAIL:
+ if (GNUNET_OK !=
+ handle_mt_avail (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ break;
+ case TALER_HELPER_CS_MT_PURGE:
+ if (GNUNET_OK !=
+ handle_mt_purge (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ break;
+ case TALER_HELPER_CS_SYNCED:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Now synchronized with CS helper\n");
+ dh->synced = true;
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Received unexpected message of type %d (len: %u)\n",
+ (unsigned int) ntohs (hdr->type),
+ (unsigned int) msize);
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ memmove (buf,
+ &buf[msize],
+ off - msize);
+ off -= msize;
+ goto more;
+ }
+}
+
+
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_cs_sign (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ const struct TALER_CRYPTO_CsSignRequest *req,
+ bool for_melt,
+ struct DONAU_BlindedDonationUnitSignature *bs)
+{
+ enum TALER_ErrorCode ec = TALER_EC_INVALID;
+ const struct TALER_CsPubHashP *h_cs = req->h_cs;
+
+ memset (bs,
+ 0,
+ sizeof (*bs));
+ 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 signature\n");
+ {
+ 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->message = *req->blinded_planchet;
+ if (GNUNET_OK !=
+ TALER_crypto_helper_send_all (dh->sock,
+ buf,
+ sizeof (buf)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "send");
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+ }
+
+ 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;
+
+ 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 ec;
+ }
+ 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 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);
+ 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_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;
+ 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:
+ if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ {
+ 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 failed with status %d!\n",
+ ec);
+ 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:
+ if (finished)
+// DONAU_blinded_donation_unit_sig_free (bs);
+ return ec;
+ }
+}
+
+
+void
+DONAU_CRYPTO_helper_cs_revoke (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ const struct TALER_CsPubHashP *h_cs)
+{
+ struct TALER_CRYPTO_CsRevokeRequest rr = {
+ .header.size = htons (sizeof (rr)),
+ .header.type = htons (TALER_HELPER_CS_MT_REQ_REVOKE),
+ .h_cs = *h_cs
+ };
+
+ if (GNUNET_OK !=
+ try_connect (dh))
+ return; /* give up */
+ if (GNUNET_OK !=
+ TALER_crypto_helper_send_all (dh->sock,
+ &rr,
+ sizeof (rr)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "send");
+ do_disconnect (dh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Requested revocation of donation unit key %s\n",
+ GNUNET_h2s (&h_cs->hash));
+}
+
+
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_cs_r_derive (struct DONAU_CRYPTO_CsDonationUnitHelper *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,
+ sizeof (*crp));
+ 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 R\n");
+ {
+ struct TALER_CRYPTO_CsRDeriveRequest rdr = {
+ .header.size = htons (sizeof (rdr)),
+ .header.type = htons (TALER_HELPER_CS_MT_REQ_RDERIVE),
+ .for_melt = htonl (for_melt ? 1 : 0),
+ .h_cs = *h_cs,
+ .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);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+ }
+
+ 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;
+
+ 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 ec;
+ }
+ 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;
+ 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 R\n");
+ finished = true;
+ ec = TALER_EC_NONE;
+ *crp = 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);
+ 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 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);
+ 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) */
+ }
+}
+
+
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_cs_batch_sign (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ unsigned int reqs_length,
+ const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length],
+ bool for_melt,
+ struct DONAU_BlindedDonationUnitSignature bss[static reqs_length])
+{
+ 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
+DONAU_CRYPTO_helper_cs_r_batch_derive (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh,
+ unsigned int cdrs_length,
+ const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length],
+ bool for_melt,
+ struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length])
+{
+ 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;
+}
+
+
+void
+DONAU_CRYPTO_helper_cs_disconnect (
+ struct DONAU_CRYPTO_CsDonationUnitHelper *dh)
+{
+ if (-1 != dh->sock)
+ do_disconnect (dh);
+ GNUNET_free (dh);
+}
+
+
+/* end of crypto_helper_cs.c */
diff --git a/src/util/crypto_helper_esign.c b/src/util/crypto_helper_esign.c
new file mode 100644
index 0000000..a4a4a40
--- /dev/null
+++ b/src/util/crypto_helper_esign.c
@@ -0,0 +1,557 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2020-2024 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
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file util/crypto_helper_esign.c
+ * @brief utility functions for running out-of-process private key operations
+ * @author Christian Grothoff
+ * @author Pius Loosli
+ */
+#include <taler/platform.h>
+#include <taler/taler_util.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler-exchange-secmod-eddsa.h>
+#include <poll.h>
+#include <crypto_helper_common.h>
+#include "donau_util.h"
+
+struct DONAU_CRYPTO_DonauSignHelper
+{
+ /**
+ * Function to call with updates to available key material.
+ */
+ DONAU_CRYPTO_DonauKeyStatusCallback dkc;
+
+ /**
+ * Closure for @e dkc
+ */
+ void *dkc_cls;
+
+ /**
+ * Socket address of the denomination helper process.
+ * Used to reconnect if the connection breaks.
+ */
+ struct sockaddr_un sa;
+
+ /**
+ * The UNIX domain socket, -1 if we are currently not connected.
+ */
+ int sock;
+
+ /**
+ * Have we reached the sync'ed state?
+ */
+ bool synced;
+
+};
+
+
+/**
+ * Disconnect from the helper process. Updates
+ * @e sock field in @a dsh.
+ *
+ * @param[in,out] dsh handle to tear down connection of
+ */
+static void
+do_disconnect (struct DONAU_CRYPTO_DonauSignHelper *dsh)
+{
+ GNUNET_break (0 == close (dsh->sock));
+ dsh->sock = -1;
+ dsh->synced = false;
+}
+
+
+/**
+ * Try to connect to the helper process. Updates
+ * @e sock field in @a dsh.
+ *
+ * @param[in,out] dsh handle to establish connection for
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+try_connect (struct DONAU_CRYPTO_DonauSignHelper *dsh)
+{
+ if (-1 != dsh->sock)
+ return GNUNET_OK;
+ dsh->sock = socket (AF_UNIX,
+ SOCK_STREAM,
+ 0);
+ if (-1 == dsh->sock)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "socket");
+ return GNUNET_SYSERR;
+ }
+ if (0 !=
+ connect (dsh->sock,
+ (const struct sockaddr *) &dsh->sa,
+ sizeof (dsh->sa)))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "connect",
+ dsh->sa.sun_path);
+ do_disconnect (dsh);
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+struct DONAU_CRYPTO_DonauSignHelper *
+DONAU_CRYPTO_helper_esign_connect (
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ DONAU_CRYPTO_DonauKeyStatusCallback dkc,
+ void *dkc_cls)
+{
+ struct DONAU_CRYPTO_DonauSignHelper *dsh;
+ char *unixpath;
+ char *secname;
+
+ GNUNET_asprintf (&secname,
+ "%s-exchange-secmod-eddsa",
+ section);
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ secname,
+ "UNIXPATH",
+ &unixpath))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ secname,
+ "UNIXPATH");
+ GNUNET_free (secname);
+ return NULL;
+ }
+ /* we use >= here because we want the sun_path to always
+ be 0-terminated */
+ if (strlen (unixpath) >= sizeof (dsh->sa.sun_path))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ secname,
+ "UNIXPATH",
+ "path too long");
+ GNUNET_free (unixpath);
+ GNUNET_free (secname);
+ return NULL;
+ }
+ GNUNET_free (secname);
+ dsh = GNUNET_new (struct DONAU_CRYPTO_DonauSignHelper);
+ dsh->dkc = dkc;
+ dsh->dkc_cls = dkc_cls;
+ dsh->sa.sun_family = AF_UNIX;
+ strncpy (dsh->sa.sun_path,
+ unixpath,
+ sizeof (dsh->sa.sun_path) - 1);
+ GNUNET_free (unixpath);
+ dsh->sock = -1;
+ if (GNUNET_OK !=
+ try_connect (dsh))
+ {
+ DONAU_CRYPTO_helper_esign_disconnect (dsh);
+ return NULL;
+ }
+
+// DONAU_CRYPTO_helper_esign_poll (dsh);
+ return dsh;
+}
+
+
+/**
+ * Handle a #TALER_HELPER_EDDSA_MT_AVAIL message from the helper.
+ *
+ * @param dsh helper context
+ * @param hdr message that we received
+ * @return #GNUNET_OK on success
+ */
+// static enum GNUNET_GenericReturnValue
+// handle_mt_avail (struct DONAU_CRYPTO_DonauSignHelper *dsh,
+// const struct GNUNET_MessageHeader *hdr)
+// {
+// const struct TALER_CRYPTO_EddsaKeyAvailableNotification *kan
+// = (const struct TALER_CRYPTO_EddsaKeyAvailableNotification *) hdr;
+//
+// if (sizeof (*kan) != ntohs (hdr->size))
+// {
+// GNUNET_break_op (0);
+// return GNUNET_SYSERR;
+// }
+//
+// if (GNUNET_OK !=
+// TALER_exchange_secmod_eddsa_verify (
+// &kan->exchange_pub,
+// GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
+// GNUNET_TIME_relative_ntoh (kan->duration),
+// &kan->secm_pub,
+// &kan->secm_sig))
+// {
+// GNUNET_break_op (0);
+// return GNUNET_SYSERR;
+// }
+// dsh->dkc (dsh->dkc_cls,
+// GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
+// GNUNET_TIME_relative_ntoh (kan->duration),
+// &kan->donau_pub,
+// &kan->secm_pub,
+// &kan->secm_sig);
+// return GNUNET_OK;
+// }
+
+
+/**
+ * Handle a #TALER_HELPER_EDDSA_MT_PURGE message from the helper.
+ *
+ * @param dsh helper context
+ * @param hdr message that we received
+ * @return #GNUNET_OK on success
+ */
+// static enum GNUNET_GenericReturnValue
+// handle_mt_purge (struct DONAU_CRYPTO_DonauSignHelper *dsh,
+// const struct GNUNET_MessageHeader *hdr)
+// {
+// const struct TALER_CRYPTO_EddsaKeyPurgeNotification *pn
+// = (const struct TALER_CRYPTO_EddsaKeyPurgeNotification *) hdr;
+//
+// if (sizeof (*pn) != ntohs (hdr->size))
+// {
+// GNUNET_break_op (0);
+// return GNUNET_SYSERR;
+// }
+// dsh->dkc (dsh->dkc_cls,
+// GNUNET_TIME_UNIT_ZERO_TS,
+// GNUNET_TIME_UNIT_ZERO,
+// &pn->exchange_pub,
+// NULL,
+// NULL);
+// return GNUNET_OK;
+// }
+
+
+// void
+// DONAU_CRYPTO_helper_esign_poll (struct DONAU_CRYPTO_DonauSignHelper *dsh)
+// {
+// char buf[UINT16_MAX];
+// size_t off = 0;
+// unsigned int retry_limit = 3;
+// const struct GNUNET_MessageHeader *hdr
+// = (const struct GNUNET_MessageHeader *) buf;
+//
+// if (GNUNET_OK !=
+// try_connect (dsh))
+// return; /* give up */
+// while (1)
+// {
+// uint16_t msize;
+// ssize_t ret;
+//
+// ret = recv (dsh->sock,
+// buf + off,
+// sizeof (buf) - off,
+// (dsh->synced && (0 == off))
+// ? MSG_DONTWAIT
+// : 0);
+// if (ret < 0)
+// {
+// if (EINTR == errno)
+// continue;
+// if (EAGAIN == errno)
+// {
+// GNUNET_assert (dsh->synced);
+// GNUNET_assert (0 == off);
+// break;
+// }
+// GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+// "recv");
+// do_disconnect (dsh);
+// if (0 == retry_limit)
+// return; /* give up */
+// if (GNUNET_OK !=
+// try_connect (dsh))
+// return; /* give up */
+// retry_limit--;
+// continue;
+// }
+// if (0 == ret)
+// {
+// GNUNET_break (0 == off);
+// return;
+// }
+// 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_EDDSA_MT_AVAIL:
+// if (GNUNET_OK !=
+// handle_mt_avail (dsh,
+// hdr))
+// {
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return;
+// }
+// break;
+// case TALER_HELPER_EDDSA_MT_PURGE:
+// if (GNUNET_OK !=
+// handle_mt_purge (dsh,
+// hdr))
+// {
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return;
+// }
+// break;
+// case TALER_HELPER_EDDSA_SYNCED:
+// GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+// "Now synchronized with EdDSA helper\n");
+// dsh->synced = true;
+// break;
+// default:
+// GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+// "Received unexpected message of type %d (len: %u)\n",
+// (unsigned int) ntohs (hdr->type),
+// (unsigned int) msize);
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return;
+// }
+// memmove (buf,
+// &buf[msize],
+// off - msize);
+// off -= msize;
+// goto more;
+// }
+// }
+
+
+// enum TALER_ErrorCode
+// DONAU_CRYPTO_helper_esign_sign_ (
+// struct DONAU_CRYPTO_DonauSignHelper *dsh,
+// const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+// struct DONAU_DonauPublicKeyP *exchange_pub,
+// struct DONAU_DonauSignatureP *exchange_sig)
+// {
+// uint32_t purpose_size = ntohl (purpose->size);
+//
+// if (GNUNET_OK !=
+// try_connect (dsh))
+// {
+// GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+// "Failed to connect to helper\n");
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE;
+// }
+// GNUNET_assert (purpose_size <
+// UINT16_MAX - sizeof (struct TALER_CRYPTO_EddsaSignRequest));
+// {
+// char buf[sizeof (struct TALER_CRYPTO_EddsaSignRequest) + purpose_size
+// - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose)];
+// struct TALER_CRYPTO_EddsaSignRequest *sr
+// = (struct TALER_CRYPTO_EddsaSignRequest *) buf;
+//
+// sr->header.size = htons (sizeof (buf));
+// sr->header.type = htons (TALER_HELPER_EDDSA_MT_REQ_SIGN);
+// sr->reserved = htonl (0);
+// GNUNET_memcpy (&sr->purpose,
+// purpose,
+// purpose_size);
+// if (GNUNET_OK !=
+// TALER_crypto_helper_send_all (dsh->sock,
+// buf,
+// sizeof (buf)))
+// {
+// GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+// "send",
+// dsh->sa.sun_path);
+// do_disconnect (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE;
+// }
+// }
+//
+// {
+// char buf[UINT16_MAX];
+// size_t off = 0;
+// const struct GNUNET_MessageHeader *hdr
+// = (const struct GNUNET_MessageHeader *) buf;
+// bool finished = false;
+// enum TALER_ErrorCode ec = TALER_EC_INVALID;
+//
+// while (1)
+// {
+// ssize_t ret;
+// uint16_t msize;
+//
+// ret = recv (dsh->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 (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE;
+// }
+// if (0 == ret)
+// {
+// GNUNET_break (0 == off);
+// if (finished)
+// return TALER_EC_NONE;
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+// }
+// 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_EDDSA_MT_RES_SIGNATURE:
+// if (msize != sizeof (struct TALER_CRYPTO_EddsaSignResponse))
+// {
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+// }
+// if (finished)
+// {
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+// }
+// {
+// const struct TALER_CRYPTO_EddsaSignResponse *sr =
+// (const struct TALER_CRYPTO_EddsaSignResponse *) buf;
+// *exchange_sig = sr->exchange_sig;
+// *exchange_pub = sr->exchange_pub;
+// finished = true;
+// ec = TALER_EC_NONE;
+// break;
+// }
+// case TALER_HELPER_EDDSA_MT_RES_SIGN_FAILURE:
+// if (msize != sizeof (struct TALER_CRYPTO_EddsaSignFailure))
+// {
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+// }
+// {
+// const struct TALER_CRYPTO_EddsaSignFailure *sf =
+// (const struct TALER_CRYPTO_EddsaSignFailure *) buf;
+//
+// finished = true;
+// ec = (enum TALER_ErrorCode) ntohl (sf->ec);
+// break;
+// }
+// case TALER_HELPER_EDDSA_MT_AVAIL:
+// if (GNUNET_OK !=
+// handle_mt_avail (dsh,
+// hdr))
+// {
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+// }
+// break; /* while(1) loop ensures we recv() again */
+// case TALER_HELPER_EDDSA_MT_PURGE:
+// if (GNUNET_OK !=
+// handle_mt_purge (dsh,
+// hdr))
+// {
+// GNUNET_break_op (0);
+// do_disconnect (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+// }
+// break; /* while(1) loop ensures we recv() again */
+// case TALER_HELPER_EDDSA_SYNCED:
+// GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+// "Synchronized add odd time with EdDSA helper!\n");
+// dsh->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 (dsh);
+// return TALER_EC_EXCHANGE_SIGNKEY_HELPER_BUG;
+// }
+// memmove (buf,
+// &buf[msize],
+// off - msize);
+// off -= msize;
+// goto more;
+// } /* while(1) */
+// return ec;
+// }
+// }
+
+
+// void
+// DONAU_CRYPTO_helper_esign_revoke (
+// struct DONAU_CRYPTO_DonauSignHelper *dsh,
+// const struct DONAU_DonauPublicKeyP *exchange_pub)
+// {
+// if (GNUNET_OK !=
+// try_connect (dsh))
+// return; /* give up */
+// {
+// struct TALER_CRYPTO_EddsaRevokeRequest rr = {
+// .header.size = htons (sizeof (rr)),
+// .header.type = htons (TALER_HELPER_EDDSA_MT_REQ_REVOKE),
+// .exchange_pub = *exchange_pub
+// };
+//
+// if (GNUNET_OK !=
+// TALER_crypto_helper_send_all (dsh->sock,
+// &rr,
+// sizeof (rr)))
+// {
+// GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+// "send");
+// do_disconnect (dsh);
+// return;
+// }
+// }
+// }
+
+
+void
+DONAU_CRYPTO_helper_esign_disconnect (
+ struct DONAU_CRYPTO_DonauSignHelper *dsh)
+{
+ if (-1 != dsh->sock)
+ do_disconnect (dsh);
+ GNUNET_free (dsh);
+}
+
+
+/* end of crypto_helper_esign.c */
diff --git a/src/util/crypto_helper_rsa.c b/src/util/crypto_helper_rsa.c
new file mode 100644
index 0000000..91edd3e
--- /dev/null
+++ b/src/util/crypto_helper_rsa.c
@@ -0,0 +1,917 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2020-2024 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
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file util/crypto_helper_rsa.c
+ * @brief utility functions for running out-of-process private key operations
+ * @author Christian Grothoff
+ * @author Pius Loosli
+ */
+#include <taler/platform.h>
+#include <taler/taler_util.h>
+#include <taler/taler_signatures.h>
+#include <taler/taler-exchange-secmod-rsa.h>
+#include <poll.h>
+#include <crypto_helper_common.h>
+#include "donau_util.h"
+
+struct DONAU_CRYPTO_RsaDonationUnitHelper
+{
+ /**
+ * Function to call with updates to available key material.
+ */
+ DONAU_CRYPTO_RsaDonationUnitKeyStatusCallback dkc;
+
+ /**
+ * Closure for @e dkc
+ */
+ void *dkc_cls;
+
+ /**
+ * Socket address of the donation unitination helper process.
+ * Used to reconnect if the connection breaks.
+ */
+ struct sockaddr_un sa;
+
+ /**
+ * The UNIX domain socket, -1 if we are currently not connected.
+ */
+ int sock;
+
+ /**
+ * Have we ever been sync'ed?
+ */
+ bool synced;
+};
+
+
+/**
+ * Disconnect from the helper process. Updates
+ * @e sock field in @a dh.
+ *
+ * @param[in,out] dh handle to tear down connection of
+ */
+static void
+do_disconnect (struct DONAU_CRYPTO_RsaDonationUnitHelper *dh)
+{
+ GNUNET_break (0 == close (dh->sock));
+ dh->sock = -1;
+ dh->synced = false;
+}
+
+
+/**
+ * Try to connect to the helper process. Updates
+ * @e sock field in @a dh.
+ *
+ * @param[in,out] dh handle to establish connection for
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+try_connect (struct DONAU_CRYPTO_RsaDonationUnitHelper *dh)
+{
+ if (-1 != dh->sock)
+ return GNUNET_OK;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Establishing connection!\n");
+ dh->sock = socket (AF_UNIX,
+ SOCK_STREAM,
+ 0);
+ if (-1 == dh->sock)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "socket");
+ return GNUNET_SYSERR;
+ }
+ if (0 !=
+ connect (dh->sock,
+ (const struct sockaddr *) &dh->sa,
+ sizeof (dh->sa)))
+ {
+ GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+ "connect",
+ dh->sa.sun_path);
+ do_disconnect (dh);
+ return GNUNET_SYSERR;
+ }
+ DONAU_CRYPTO_helper_rsa_poll (dh);
+ return GNUNET_OK;
+}
+
+
+struct DONAU_CRYPTO_RsaDonationUnitHelper *
+DONAU_CRYPTO_helper_rsa_connect (
+ const struct GNUNET_CONFIGURATION_Handle *cfg,
+ const char *section,
+ DONAU_CRYPTO_RsaDonationUnitKeyStatusCallback dkc,
+ void *dkc_cls)
+{
+ struct DONAU_CRYPTO_RsaDonationUnitHelper *dh;
+ char *unixpath;
+ char *secname;
+
+ GNUNET_asprintf (&secname,
+ "%s-exchange-secmod-rsa",
+ section);
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_filename (cfg,
+ secname,
+ "UNIXPATH",
+ &unixpath))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ secname,
+ "UNIXPATH");
+ GNUNET_free (secname);
+ return NULL;
+ }
+ /* we use >= here because we want the sun_path to always
+ be 0-terminated */
+ if (strlen (unixpath) >= sizeof (dh->sa.sun_path))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ "taler-exchange-secmod-rsa",
+ "UNIXPATH",
+ "path too long");
+ GNUNET_free (unixpath);
+ GNUNET_free (secname);
+ return NULL;
+ }
+ GNUNET_free (secname);
+ dh = GNUNET_new (struct DONAU_CRYPTO_RsaDonationUnitHelper);
+ dh->dkc = dkc;
+ dh->dkc_cls = dkc_cls;
+ dh->sa.sun_family = AF_UNIX;
+ strncpy (dh->sa.sun_path,
+ unixpath,
+ sizeof (dh->sa.sun_path) - 1);
+ GNUNET_free (unixpath);
+ dh->sock = -1;
+ if (GNUNET_OK !=
+ try_connect (dh))
+ {
+ DONAU_CRYPTO_helper_rsa_disconnect (dh);
+ return NULL;
+ }
+ return dh;
+}
+
+
+/**
+ * Handle a #TALER_HELPER_RSA_MT_AVAIL message from the helper.
+ *
+ * @param dh helper context
+ * @param hdr message that we received
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+handle_mt_avail (struct DONAU_CRYPTO_RsaDonationUnitHelper *dh,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ const struct TALER_CRYPTO_RsaKeyAvailableNotification *kan
+ = (const struct TALER_CRYPTO_RsaKeyAvailableNotification *) hdr;
+ const char *buf = (const char *) &kan[1];
+ const char *section_name;
+ uint16_t ps;
+ uint16_t snl;
+
+ if (sizeof (*kan) > ntohs (hdr->size))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ ps = ntohs (kan->pub_size);
+ snl = ntohs (kan->section_name_len);
+ if (ntohs (hdr->size) != sizeof (*kan) + ps + snl)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ if (0 == snl)
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ section_name = &buf[ps];
+ if ('\0' != section_name[snl - 1])
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+
+ {
+ struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub;
+ struct TALER_RsaPubHashP h_rsa;
+
+ bs_pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+ bs_pub->cipher = GNUNET_CRYPTO_BSA_RSA;
+ bs_pub->details.rsa_public_key
+ = GNUNET_CRYPTO_rsa_public_key_decode (buf,
+ ntohs (kan->pub_size));
+ if (NULL == bs_pub->details.rsa_public_key)
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (bs_pub);
+ return GNUNET_SYSERR;
+ }
+ bs_pub->rc = 1;
+ GNUNET_CRYPTO_rsa_public_key_hash (bs_pub->details.rsa_public_key,
+ &bs_pub->pub_key_hash);
+ h_rsa.hash = bs_pub->pub_key_hash;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received RSA key %s (%s)\n",
+ GNUNET_h2s (&bs_pub->pub_key_hash),
+ section_name);
+ if (GNUNET_OK !=
+ TALER_exchange_secmod_rsa_verify (
+ &h_rsa,
+ section_name,
+ GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
+ GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
+ &kan->secm_pub,
+ &kan->secm_sig))
+ {
+ GNUNET_break_op (0);
+ GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
+ return GNUNET_SYSERR;
+ }
+ dh->dkc (dh->dkc_cls,
+ section_name,
+ GNUNET_TIME_timestamp_ntoh (kan->anchor_time),
+ GNUNET_TIME_relative_ntoh (kan->duration_withdraw),
+ &h_rsa,
+ bs_pub,
+ &kan->secm_pub,
+ &kan->secm_sig);
+ GNUNET_CRYPTO_blind_sign_pub_decref (bs_pub);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Handle a #TALER_HELPER_RSA_MT_PURGE message from the helper.
+ *
+ * @param dh helper context
+ * @param hdr message that we received
+ * @return #GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+handle_mt_purge (struct DONAU_CRYPTO_RsaDonationUnitHelper *dh,
+ const struct GNUNET_MessageHeader *hdr)
+{
+ const struct TALER_CRYPTO_RsaKeyPurgeNotification *pn
+ = (const struct TALER_CRYPTO_RsaKeyPurgeNotification *) hdr;
+
+ if (sizeof (*pn) != ntohs (hdr->size))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received revocation of donation unit key %s\n",
+ GNUNET_h2s (&pn->h_rsa.hash));
+ dh->dkc (dh->dkc_cls,
+ NULL,
+ GNUNET_TIME_UNIT_ZERO_TS,
+ GNUNET_TIME_UNIT_ZERO,
+ &pn->h_rsa,
+ NULL,
+ NULL,
+ NULL);
+ return GNUNET_OK;
+}
+
+
+void
+DONAU_CRYPTO_helper_rsa_poll (struct DONAU_CRYPTO_RsaDonationUnitHelper *dh)
+{
+ char buf[UINT16_MAX];
+ size_t off = 0;
+ unsigned int retry_limit = 3;
+ const struct GNUNET_MessageHeader *hdr
+ = (const struct GNUNET_MessageHeader *) buf;
+
+ if (GNUNET_OK !=
+ try_connect (dh))
+ return; /* give up */
+ while (1)
+ {
+ uint16_t msize;
+ ssize_t ret;
+
+ ret = recv (dh->sock,
+ buf + off,
+ sizeof (buf) - off,
+ (dh->synced && (0 == off))
+ ? MSG_DONTWAIT
+ : 0);
+ if (ret < 0)
+ {
+ if (EINTR == errno)
+ continue;
+ if (EAGAIN == errno)
+ {
+ GNUNET_assert (dh->synced);
+ GNUNET_assert (0 == off);
+ break;
+ }
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "recv");
+ do_disconnect (dh);
+ if (0 == retry_limit)
+ return; /* give up */
+ if (GNUNET_OK !=
+ try_connect (dh))
+ return; /* give up */
+ retry_limit--;
+ continue;
+ }
+ if (0 == ret)
+ {
+ GNUNET_break (0 == off);
+ return;
+ }
+ off += ret;
+more:
+ if (off < sizeof (struct GNUNET_MessageHeader))
+ continue;
+ msize = ntohs (hdr->size);
+ if (off < msize)
+ continue;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Received message of type %u and length %u\n",
+ (unsigned int) ntohs (hdr->type),
+ (unsigned int) msize);
+ switch (ntohs (hdr->type))
+ {
+ case TALER_HELPER_RSA_MT_AVAIL:
+ if (GNUNET_OK !=
+ handle_mt_avail (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ break;
+ case TALER_HELPER_RSA_MT_PURGE:
+ if (GNUNET_OK !=
+ handle_mt_purge (dh,
+ hdr))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ break;
+ case TALER_HELPER_RSA_SYNCED:
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Now synchronized with RSA helper\n");
+ dh->synced = true;
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Received unexpected message of type %d (len: %u)\n",
+ (unsigned int) ntohs (hdr->type),
+ (unsigned int) msize);
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return;
+ }
+ memmove (buf,
+ &buf[msize],
+ off - msize);
+ off -= msize;
+ goto more;
+ }
+}
+
+
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_rsa_sign (
+ struct DONAU_CRYPTO_RsaDonationUnitHelper *dh,
+ const struct TALER_CRYPTO_RsaSignRequest *rsr,
+ struct DONAU_BlindedDonationUnitSignature *bs)
+{
+ enum TALER_ErrorCode ec = TALER_EC_INVALID;
+
+ memset (bs,
+ 0,
+ sizeof (*bs));
+ 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 signature\n");
+ {
+ char buf[sizeof (struct TALER_CRYPTO_SignRequest) + rsr->msg_size];
+ struct TALER_CRYPTO_SignRequest *sr
+ = (struct TALER_CRYPTO_SignRequest *) buf;
+
+ sr->header.size = htons (sizeof (buf));
+ sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
+ sr->reserved = htonl (0);
+ sr->h_rsa = *rsr->h_rsa;
+ GNUNET_memcpy (&sr[1],
+ rsr->msg,
+ rsr->msg_size);
+ if (GNUNET_OK !=
+ TALER_crypto_helper_send_all (dh->sock,
+ buf,
+ sizeof (buf)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "send");
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ }
+ }
+
+ 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;
+
+ 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 ec;
+ }
+ 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 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_RSA_MT_RES_SIGNATURE:
+ if (msize < sizeof (struct TALER_CRYPTO_SignResponse))
+ {
+ 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_SignResponse *sr =
+ (const struct TALER_CRYPTO_SignResponse *) buf;
+ struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+ struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
+
+ rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
+ &sr[1],
+ msize - sizeof (*sr));
+ if (NULL == rsa_signature)
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received signature\n");
+ ec = TALER_EC_NONE;
+ finished = true;
+ blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+ blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
+ blind_sig->rc = 1;
+ blind_sig->details.blinded_rsa_signature = rsa_signature;
+ bs->blinded_sig = blind_sig;
+ break;
+ }
+ case TALER_HELPER_RSA_MT_RES_SIGN_FAILURE:
+ if (msize != sizeof (struct TALER_CRYPTO_SignFailure))
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ goto end;
+ }
+ {
+ 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 failed!\n");
+ finished = true;
+ break;
+ }
+ case TALER_HELPER_RSA_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_RSA_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_RSA_SYNCED:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Synchronized add odd time with RSA 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:
+ if (finished)
+// DONAU_blinded_donation_unit_sig_free(bs);
+ return ec;
+ }
+}
+
+
+enum TALER_ErrorCode
+DONAU_CRYPTO_helper_rsa_batch_sign (
+ struct DONAU_CRYPTO_RsaDonationUnitHelper *dh,
+ unsigned int rsrs_length,
+ const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length],
+ struct DONAU_BlindedDonationUnitSignature bss[static rsrs_length])
+{
+ enum TALER_ErrorCode ec = TALER_EC_INVALID;
+ unsigned int rpos;
+ unsigned int rend;
+ unsigned int wpos;
+
+ memset (bss,
+ 0,
+ sizeof (*bss) * rsrs_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",
+ rsrs_length);
+ rpos = 0;
+ rend = 0;
+ wpos = 0;
+ while (rpos < rsrs_length)
+ {
+ unsigned int mlen = sizeof (struct TALER_CRYPTO_BatchSignRequest);
+
+ while ( (rend < rsrs_length) &&
+ (mlen
+ + sizeof (struct TALER_CRYPTO_SignRequest)
+ + rsrs[rend].msg_size < UINT16_MAX) )
+ {
+ mlen += sizeof (struct TALER_CRYPTO_SignRequest) + rsrs[rend].msg_size;
+ rend++;
+ }
+ {
+ char obuf[mlen] GNUNET_ALIGN;
+ struct TALER_CRYPTO_BatchSignRequest *bsr
+ = (struct TALER_CRYPTO_BatchSignRequest *) obuf;
+ void *wbuf;
+
+ bsr->header.type = htons (TALER_HELPER_RSA_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_SignRequest *sr = wbuf;
+ const struct TALER_CRYPTO_RsaSignRequest *rsr = &rsrs[i];
+
+ sr->header.type = htons (TALER_HELPER_RSA_MT_REQ_SIGN);
+ sr->header.size = htons (sizeof (*sr) + rsr->msg_size);
+ sr->reserved = htonl (0);
+ sr->h_rsa = *rsr->h_rsa;
+ GNUNET_memcpy (&sr[1],
+ rsr->msg,
+ rsr->msg_size);
+ wbuf += sizeof (*sr) + rsr->msg_size;
+ }
+ 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;
+ }
+ }
+ 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);
+ ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE;
+ break;
+ }
+ if (0 == ret)
+ {
+ GNUNET_break (0 == off);
+ if (! finished)
+ ec = 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_RSA_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_RsaSignature *rsa_signature;
+ struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
+
+ rsa_signature = GNUNET_CRYPTO_rsa_signature_decode (
+ &sr[1],
+ msize - sizeof (*sr));
+ if (NULL == rsa_signature)
+ {
+ GNUNET_break_op (0);
+ do_disconnect (dh);
+ return TALER_EC_EXCHANGE_DENOMINATION_HELPER_BUG;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Received %u signature\n",
+ wpos);
+ blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+ blind_sig->cipher = GNUNET_CRYPTO_BSA_RSA;
+ blind_sig->rc = 1;
+ blind_sig->details.blinded_rsa_signature = rsa_signature;
+ bss[wpos].blinded_sig = blind_sig;
+ wpos++;
+ if (wpos == rend)
+ {
+ if (TALER_EC_INVALID == ec)
+ ec = TALER_EC_NONE;
+ finished = true;
+ }
+ break;
+ }
+ case TALER_HELPER_RSA_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_RSA_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_RSA_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_RSA_SYNCED:
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Synchronized add odd time with RSA 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 < rsrs_length) */
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Existing with %u signatures and status %d\n",
+ wpos,
+ ec);
+ return ec;
+}
+
+
+void
+DONAU_CRYPTO_helper_rsa_revoke (
+ struct DONAU_CRYPTO_RsaDonationUnitHelper *dh,
+ const struct TALER_RsaPubHashP *h_rsa)
+{
+ struct TALER_CRYPTO_RevokeRequest rr = {
+ .header.size = htons (sizeof (rr)),
+ .header.type = htons (TALER_HELPER_RSA_MT_REQ_REVOKE),
+ .h_rsa = *h_rsa
+ };
+
+ if (GNUNET_OK !=
+ try_connect (dh))
+ return; /* give up */
+ if (GNUNET_OK !=
+ TALER_crypto_helper_send_all (dh->sock,
+ &rr,
+ sizeof (rr)))
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "send");
+ do_disconnect (dh);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Requested revocation of donation unit key %s\n",
+ GNUNET_h2s (&h_rsa->hash));
+}
+
+
+void
+DONAU_CRYPTO_helper_rsa_disconnect (
+ struct DONAU_CRYPTO_RsaDonationUnitHelper *dh)
+{
+ if (-1 != dh->sock)
+ do_disconnect (dh);
+ GNUNET_free (dh);
+}
+
+
+/* end of crypto_helper_donation_unit.c */
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.