donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit 995ba60e993586dd42d97de4407f301f0cc7c20b
parent afc7557882e41c13ae1c59f29b2292eb696a87dc
Author: Pius Loosli <loosp2@bfh.ch>
Date:   Sat,  6 Jan 2024 21:47:50 +0100

[donau] First iteration on /keys: adapt structs to donau starting from exchange /management/keys

Diffstat:
Msrc/donau/Makefile.am | 1-
Msrc/donau/donau-httpd.c | 21+++++++++++++--------
Msrc/donau/donau-httpd_keys.c | 285++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Msrc/donau/donau-httpd_keys.h | 4++--
Msrc/include/donau_crypto_lib.h | 1+
5 files changed, 242 insertions(+), 70 deletions(-)

diff --git a/src/donau/Makefile.am b/src/donau/Makefile.am @@ -27,7 +27,6 @@ donau_httpd_LDADD = \ -lmicrohttpd \ -ltalermhd \ -ltalerutil \ - -ltalertemplating \ -lgnunetcurl \ -lgnunetutil \ -lgnunetjson \ diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c @@ -50,7 +50,7 @@ * Above what request latency do we start to log? */ #define WARN_LATENCY GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_MILLISECONDS, 500) + GNUNET_TIME_UNIT_MILLISECONDS, 500) /** * Are clients allowed to request /keys for times other than the @@ -394,16 +394,16 @@ proceed_with_handler (struct DH_RequestContext *rc, * @return MHD result code */ static MHD_RESULT -handle_get_management (struct DH_RequestContext *rc, - const char *const args[2]) +handle_get_keys (struct DH_RequestContext *rc, + const char *const args[2]) { if ( (NULL != args[0]) && (0 == strcmp (args[0], "keys")) && (NULL == args[1]) ) { - return DH_keys_management_get_keys_handler (rc->rh, - rc->connection); + return DH_get_keys_handler (rc->rh, + rc->connection); } GNUNET_break_op (0); return r404 (rc->connection, @@ -450,13 +450,18 @@ handle_mhd_request (void *cls, .method = MHD_HTTP_METHOD_GET, .handler.get = &DH_handler_config }, - /* GET management endpoints (we only really have "/management/keys") */ + /* GET keys endpoints (we only really have "/keys") */ { - .url = "management", + .url = "keys", .method = MHD_HTTP_METHOD_GET, - .handler.get = &handle_get_management, + .handler.get = &handle_get_keys, .nargs = 1 }, + /** + etc + + Add routes here + */ /* mark end of list */ { .url = NULL diff --git a/src/donau/donau-httpd_keys.c b/src/donau/donau-httpd_keys.c @@ -24,8 +24,7 @@ #include "taler/taler_mhd_lib.h" #include "donau-httpd.h" #include "donau-httpd_keys.h" -// #include "donau-httpd_config.h" -// #include "donau-httpd_responses.h" +#include "donau-httpd_config.h" #include "donaudb_plugin.h" @@ -36,6 +35,77 @@ #define SKR_LIMIT 32 /** + * Information about a donation unit on offer by the donation unit helper. + */ +struct HelperDonationUnit +{ + + /** + * When will the helper start to use this key for signing? + */ + struct GNUNET_TIME_Timestamp start_time; + + /** + * For how long will the helper allow signing? 0 if + * the key was revoked or purged. + */ + struct GNUNET_TIME_Relative validity_duration; + + /** + * Hash of the full donation unit key. + */ + struct DONAU_DonationUnitHashP h_donation_unit_pub; + + /** + * The (full) public key. + */ + struct DONAU_DonationUnitPublicKey donation_unit_pub; + + /** + * Details depend on the @e donation_unit_pub.cipher type. + */ + union + { + + /** + * Hash of the RSA key. + */ + struct TALER_RsaPubHashP h_rsa; + + /** + * Hash of the CS key. + */ + struct TALER_CsPubHashP h_cs; + + } h_details; + + /** + * Name in configuration section for this donation unit type. + */ + char *section_name; + + +}; + +/** + * Information about a signing key on offer by the sign helper. + */ +struct HelperSignkey +{ + /** + * When will the helper start to use this key for signing? + */ + // struct GNUNET_TIME_Timestamp start_time; + int year; + + /** + * The public key. + */ + struct DONAU_DonauPublicKeyP donau_pub; + +}; + +/** * Counter incremented whenever we have a reason to re-build the keys because * something external changed. See #DH_keys_get_state() and * #DH_keys_update_states() for uses of this variable. @@ -64,13 +134,6 @@ static struct TALER_SecurityModulePublicKeyP esign_sm_pub; #define KEYS_TIMEOUT GNUNET_TIME_UNIT_MINUTES /** - * Obtain the key state if we should NOT run finish_keys_response() because we - * only need the state for the /management/keys API - */ -struct DH_KeyStateHandle * -DH_keys_get_state_for_management_only (void); - -/** * Stores the latest generation of our key state. */ static struct DH_KeyStateHandle *key_state; @@ -98,13 +161,13 @@ struct DH_KeyStateHandle { /** - * Mapping from denomination keys to denomination key issue struct. + * Mapping from donation unit keys to donation unit key issue struct. * Used to lookup the key by hash. */ struct GNUNET_CONTAINER_MultiHashMap *denomkey_map; /** - * Map from `struct TALER_ExchangePublicKey` to `struct SigningKey` + * Map from `struct DONAU_DonauPublicKey` to `struct SigningKey` * entries. Based on the fact that a `struct GNUNET_PeerIdentity` is also * an EdDSA public key. */ @@ -244,18 +307,13 @@ struct HelperState struct DenomKeyCtx { /** - * Heap for sorting active denomination keys by start time. + * Heap for sorting active donation unit keys by start time. */ struct GNUNET_CONTAINER_Heap *heap; /** - * JSON array of revoked denomination keys. - */ - json_t *recoup; - - /** * What is the minimum key rotation frequency of - * valid denomination keys? + * valid donation unit keys? */ struct GNUNET_TIME_Relative min_dk_frequency; }; @@ -373,7 +431,7 @@ finish_keys_response (struct DH_KeyStateHandle *ksh) enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR; json_t *recoup; struct SignKeyCtx sctx; - json_t *grouped_denominations = NULL; + json_t *grouped_donation_units = NULL; struct GNUNET_TIME_Timestamp last_cherry_pick_date; struct GNUNET_CONTAINER_Heap *heap; struct GNUNET_HashContext *hash_context = NULL; @@ -405,8 +463,8 @@ finish_keys_response (struct DH_KeyStateHandle *ksh) hash_context = GNUNET_CRYPTO_hash_context_start (); - grouped_denominations = json_array (); - GNUNET_assert (NULL != grouped_denominations); + grouped_donation_units = json_array (); + GNUNET_assert (NULL != grouped_donation_units); last_cherry_pick_date = GNUNET_TIME_UNIT_ZERO_TS; @@ -436,14 +494,14 @@ finish_keys_response (struct DH_KeyStateHandle *ksh) else { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "No denomination keys available. Refusing to generate /keys response.\n"); + "No donation unit keys available. Refusing to generate /keys response.\n"); GNUNET_CRYPTO_hash_context_abort (hash_context); } ret = GNUNET_OK; CLEANUP: - json_decref (grouped_denominations); + json_decref (grouped_donation_units); json_decref (sctx.signkeys); json_decref (recoup); return ret; @@ -451,17 +509,17 @@ CLEANUP: /** - * Free denomination key data. + * Free donation unit key data. * * @param cls a `struct DH_KeyStateHandle`, unused - * @param h_donation_unit_pub hash of the denomination public key, unused + * @param h_donation_unit_pub hash of the donation unit public key, unused * @param value a `struct DH_DonationUnitKey` to free * @return #GNUNET_OK (continue to iterate) */ static enum GNUNET_GenericReturnValue -clear_denomination_cb (void *cls, - const struct GNUNET_HashCode *h_donation_unit_pub, - void *value) +clear_donation_unit_cb (void *cls, + const struct GNUNET_HashCode *h_donation_unit_pub, + void *value) { struct DH_DonationUnitKey *dk = value; @@ -474,7 +532,7 @@ clear_denomination_cb (void *cls, /** - * Free denomination key data. + * Free donation unit key data. * * @param cls a `struct DH_KeyStateHandle`, unused * @param pid the online signing key (type-disguised), unused @@ -594,7 +652,7 @@ destroy_key_state (struct DH_KeyStateHandle *ksh, // GNUNET_free (gf); // } GNUNET_CONTAINER_multihashmap_iterate (ksh->denomkey_map, - &clear_denomination_cb, + &clear_donation_unit_cb, ksh); GNUNET_CONTAINER_multihashmap_destroy (ksh->denomkey_map); GNUNET_CONTAINER_multipeermap_iterate (ksh->signkey_map, @@ -788,7 +846,7 @@ keys_get_state (bool management_only) old_ksh = key_state; if (NULL == old_ksh) { - // ksh = build_key_state (NULL, management_only); + ksh = build_key_state (NULL, management_only); ksh = NULL; if (NULL == ksh) return NULL; @@ -815,23 +873,134 @@ keys_get_state (bool management_only) } -struct DH_KeyStateHandle * -DH_keys_get_state_for_management_only (void) +/** + * Closure for #add_future_donation_unit_cb and #add_future_signkey_cb. + */ +struct FutureBuilderContext { - return keys_get_state (true); + /** + * Our key state. + */ + struct DH_KeyStateHandle *ksh; + + /** + * Array of donation unit keys. + */ + json_t *donation_units; + + /** + * Array of signing keys. + */ + json_t *signkeys; + +}; + +/** + * Function called on all of our current and future donation unit keys + * known to the helper process. Filters out those that are current + * and adds the remaining donation unit keys (with their configuration + * data) to the JSON array. + * + * @param cls the `struct FutureBuilderContext *` + * @param h_donation_unit_pub hash of the donation unit public key + * @param value a `struct HelperDenomination` + * @return #GNUNET_OK (continue to iterate) + */ +static enum GNUNET_GenericReturnValue +add_donation_unitkey_cb (void *cls, + const struct GNUNET_HashCode *h_donation_unit_pub, + void *value) +{ + struct FutureBuilderContext *fbc = cls; + struct HelperDonationUnit *helper_donation_unit = value; + struct DH_DonationUnitKey *donation_unit_key; + struct DONAUDB_DonationUnitKeyMetaData meta = {0}; + + donation_unit_key = GNUNET_CONTAINER_multihashmap_get (fbc->ksh->denomkey_map, + h_donation_unit_pub); + if (NULL != donation_unit_key) + return GNUNET_OK; /* skip: this key is already active! */ + // if (GNUNET_TIME_relative_is_zero (hd->validity_duration)) + // return GNUNET_OK; /* this key already expired! */ + + GNUNET_assert ( + 0 == + json_array_append_new ( + fbc->donation_units, + GNUNET_JSON_PACK ( + TALER_JSON_pack_amount ("value", + &meta.value), + GNUNET_JSON_pack_uint64 ("year", + meta.validity_year), + GNUNET_JSON_pack_data_auto ("donation_unit_pub", + &helper_donation_unit->donation_unit_pub) + // GNUNET_JSON_pack_string ("section_name", + // helper_donation_unit->section_name) + ))); + return GNUNET_OK; +} + + +/** + * Function called on all of our current and future exchange signing keys + * known to the helper process. Filters out those that are current + * and adds the remaining signing keys (with their configuration + * data) to the JSON array. + * + * @param cls the `struct FutureBuilderContext *` + * @param pid actually the exchange public key (type disguised) + * @param value a `struct HelperDenomination` + * @return #GNUNET_OK (continue to iterate) + */ +static enum GNUNET_GenericReturnValue +add_signkey_cb (void *cls, + const struct GNUNET_PeerIdentity *pid, + void *value) +{ + struct FutureBuilderContext *fbc = cls; + struct HelperSignkey *hsk = value; + struct SigningKey *sk; + // struct GNUNET_TIME_Timestamp stamp_expire; + // struct GNUNET_TIME_Timestamp legal_end; + + sk = GNUNET_CONTAINER_multipeermap_get (fbc->ksh->signkey_map, + pid); + if (NULL != sk) + return GNUNET_OK; /* skip: this key is already active */ + // if (GNUNET_TIME_relative_is_zero (hsk->validity_duration)) + // return GNUNET_OK; /* this key already expired! */ + // stamp_expire = GNUNET_TIME_absolute_to_timestamp ( + // GNUNET_TIME_absolute_add (hsk->start_time.abs_time, + // hsk->validity_duration)); + // legal_end = GNUNET_TIME_absolute_to_timestamp ( + // GNUNET_TIME_absolute_add (stamp_expire.abs_time, + // signkey_legal_duration)); + GNUNET_assert (0 == + json_array_append_new ( + fbc->signkeys, + GNUNET_JSON_PACK ( + GNUNET_JSON_pack_data_auto ("key", + &hsk->donau_pub), + // GNUNET_JSON_pack_timestamp ("stamp_end", + // legal_end), + GNUNET_JSON_pack_data_auto ("year", + &hsk->year) + // GNUNET_JSON_pack_data_auto ("signkey_secmod_sig", + // &hsk->sm_sig) + ))); + return GNUNET_OK; } MHD_RESULT -DH_keys_management_get_keys_handler (const struct DH_RequestHandler *rh, - struct MHD_Connection *connection) +DH_get_keys_handler (const struct DH_RequestHandler *rh, + struct MHD_Connection *connection) { struct DH_KeyStateHandle *ksh; json_t *reply; (void) rh; - // ksh = DH_keys_get_state_for_management_only (); - ksh = NULL; + ksh = keys_get_state (true); if (NULL == ksh) { return TALER_MHD_reply_with_error (connection, @@ -842,15 +1011,15 @@ DH_keys_management_get_keys_handler (const struct DH_RequestHandler *rh, sync_key_helpers (ksh->helpers); if (NULL == ksh->management_keys_reply) { - // struct FutureBuilderContext fbc = { - // .ksh = ksh, - // .donation_units = json_array (), - // .signkeys = json_array () - // }; + struct FutureBuilderContext fbc = { + .ksh = ksh, + .donation_units = json_array (), + .signkeys = json_array () + }; if ( (GNUNET_is_zero (&donation_unit_rsa_sm_pub)) && (GNUNET_is_zero (&donation_unit_cs_sm_pub)) ) { - /* Either IPC failed, or neither helper had any donation_unitinations configured. */ + /* Either IPC failed, or neither helper had any donation_unit configured. */ return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_GATEWAY, TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE, @@ -863,21 +1032,19 @@ DH_keys_management_get_keys_handler (const struct DH_RequestHandler *rh, TALER_EC_EXCHANGE_SIGNKEY_HELPER_UNAVAILABLE, NULL); } - // GNUNET_assert (NULL != fbc.donation_units); - // GNUNET_assert (NULL != fbc.signkeys); - // GNUNET_CONTAINER_multihashmap_iterate (ksh->helpers->donation_unit_keys, - // &add_future_donation_unitkey_cb, - // &fbc); - // GNUNET_CONTAINER_multipeermap_iterate (ksh->helpers->esign_keys, - // &add_future_signkey_cb, - // &fbc); + GNUNET_assert (NULL != fbc.donation_units); + GNUNET_assert (NULL != fbc.signkeys); + GNUNET_CONTAINER_multihashmap_iterate (ksh->helpers->donation_unit_keys, + &add_donation_unitkey_cb, + &fbc); + GNUNET_CONTAINER_multipeermap_iterate (ksh->helpers->esign_keys, + &add_signkey_cb, + &fbc); reply = GNUNET_JSON_PACK ( - // GNUNET_JSON_pack_array_steal ("future_donation_units", - // fbc.donation_units), - // GNUNET_JSON_pack_array_steal ("future_signkeys", - // fbc.signkeys), - // GNUNET_JSON_pack_data_auto ("master_pub", - // &DH_master_public_key), + GNUNET_JSON_pack_array_steal ("future_donation_units", + fbc.donation_units), + GNUNET_JSON_pack_array_steal ("future_signkeys", + fbc.signkeys), GNUNET_JSON_pack_data_auto ("donation_unit_secmod_public_key", &donation_unit_rsa_sm_pub), GNUNET_JSON_pack_data_auto ("donation_unit_secmod_cs_public_key", @@ -885,7 +1052,7 @@ DH_keys_management_get_keys_handler (const struct DH_RequestHandler *rh, GNUNET_JSON_pack_data_auto ("signkey_secmod_public_key", &esign_sm_pub)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Returning GET /management/keys response:\n"); + "Returning GET /keys response:\n"); if (NULL == reply) return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, diff --git a/src/donau/donau-httpd_keys.h b/src/donau/donau-httpd_keys.h @@ -65,8 +65,8 @@ struct DH_DonationUnitKey * @return MHD result code */ MHD_RESULT -DH_keys_management_get_keys_handler (const struct DH_RequestHandler *rh, - struct MHD_Connection *connection); +DH_get_keys_handler (const struct DH_RequestHandler *rh, + struct MHD_Connection *connection); #endif diff --git a/src/include/donau_crypto_lib.h b/src/include/donau_crypto_lib.h @@ -31,6 +31,7 @@ #include <gnunet/gnunet_util_lib.h> #include "taler/taler_error_codes.h" +#include "taler/taler_util.h" #include <gcrypt.h> #include <jansson.h>