From e0b62b0a49672bd259ed47c9448b78c9be8823f7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 5 Dec 2020 21:33:30 +0100 Subject: towards offline tool uploading /management/keys --- src/exchange-tools/taler-exchange-offline.c | 475 ++++++++++++++++++++- .../taler-exchange-httpd_management_post_keys.c | 40 +- src/include/taler_crypto_lib.h | 65 +++ src/lib/exchange_api_handle.c | 46 +- src/util/offline_signatures.c | 91 ++++ 5 files changed, 651 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/exchange-tools/taler-exchange-offline.c b/src/exchange-tools/taler-exchange-offline.c index c4804fead..e8a2fb39f 100644 --- a/src/exchange-tools/taler-exchange-offline.c +++ b/src/exchange-tools/taler-exchange-offline.c @@ -229,6 +229,33 @@ struct WireFeeRequest }; +/** + * Ongoing /keys request. + */ +struct UploadKeysRequest +{ + /** + * Kept in a DLL. + */ + struct UploadKeysRequest *next; + + /** + * Kept in a DLL. + */ + struct UploadKeysRequest *prev; + + /** + * Operation handle. + */ + struct TALER_EXCHANGE_ManagementPostKeysHandle *h; + + /** + * Operation index. + */ + size_t idx; +}; + + /** * Next work item to perform. */ @@ -249,7 +276,6 @@ static struct DenomRevocationRequest *drr_head; */ static struct DenomRevocationRequest *drr_tail; - /** * Active signkey revocation requests. */ @@ -260,7 +286,6 @@ static struct SignkeyRevocationRequest *srr_head; */ static struct SignkeyRevocationRequest *srr_tail; - /** * Active wire add requests. */ @@ -291,6 +316,16 @@ static struct WireFeeRequest *wfr_head; */ static struct WireFeeRequest *wfr_tail; +/** + * Active keys upload requests. + */ +static struct UploadKeysRequest *ukr_head; + +/** + * Active keys upload requests. + */ +static struct UploadKeysRequest *ukr_tail; + /** * Shutdown task. Invoked when the application is being terminated. @@ -378,6 +413,21 @@ do_shutdown (void *cls) GNUNET_free (wfr); } } + { + struct UploadKeysRequest *ukr; + + while (NULL != (ukr = ukr_head)) + { + fprintf (stderr, + "Aborting incomplete key signature upload #%u\n", + (unsigned int) ukr->idx); + TALER_EXCHANGE_post_management_keys_cancel (ukr->h); + GNUNET_CONTAINER_DLL_remove (ukr_head, + ukr_tail, + ukr); + GNUNET_free (ukr); + } + } if (NULL != out) { json_dumpf (out, @@ -427,6 +477,7 @@ test_shutdown (void) (NULL == war_head) && (NULL == wdr_head) && (NULL == wfr_head) && + (NULL == ukr_head) && (NULL == mgkh) && (NULL == nxt) ) GNUNET_SCHEDULER_shutdown (); @@ -1016,6 +1067,67 @@ upload_wire_fee (const char *exchange_url, } +/** + * Function called with information about the post upload keys operation result. + * + * @param cls closure with a `struct UploadKeysRequest` + * @param hr HTTP response data + */ +static void +keys_cb ( + void *cls, + const struct TALER_EXCHANGE_HttpResponse *hr) +{ + struct UploadKeysRequest *ukr = cls; + + if (MHD_HTTP_NO_CONTENT != hr->http_status) + { + fprintf (stderr, + "Upload failed for command %u with status %u: %s (%s)\n", + (unsigned int) ukr->idx, + hr->http_status, + TALER_ErrorCode_get_hint (hr->ec), + hr->hint); + } + GNUNET_CONTAINER_DLL_remove (ukr_head, + ukr_tail, + ukr); + GNUNET_free (ukr); + test_shutdown (); +} + + +/** + * Upload (denomination and signing) key master signatures. + * + * @param exchange_url base URL of the exchange + * @param idx index of the operation we are performing (for logging) + * @param value argumets for POSTing keys + */ +static void +upload_keys (const char *exchange_url, + size_t idx, + const json_t *value) +{ + struct TALER_EXCHANGE_ManagementPostKeysData pkd; + struct UploadKeysRequest *ukr; + + // FIXME: initialize 'pkd' from 'value'! + + ukr = GNUNET_new (struct UploadKeysRequest); + ukr->idx = idx; + ukr->h = + TALER_EXCHANGE_post_management_keys (ctx, + exchange_url, + &pkd, + &keys_cb, + ukr); + GNUNET_CONTAINER_DLL_insert (ukr_head, + ukr_tail, + ukr); +} + + /** * Perform uploads based on the JSON in #io. * @@ -1045,7 +1157,10 @@ trigger_upload (const char *exchange_url) .key = "set-wire-fee", .cb = &upload_wire_fee }, - // FIXME: Add POST /management/keys handlers here! + { + .key = "upload-keys", + .cb = &upload_keys + }, /* array termination */ { .key = NULL @@ -1697,6 +1812,7 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, struct TALER_DenominationPublicKey denom_pub; struct GNUNET_TIME_Absolute stamp_start; struct GNUNET_TIME_Absolute stamp_expire_withdraw; + struct GNUNET_TIME_Absolute stamp_expire_deposit; struct GNUNET_TIME_Absolute stamp_expire_legal; struct TALER_Amount coin_value; struct TALER_Amount fee_withdraw; @@ -1723,6 +1839,8 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, &stamp_start), GNUNET_JSON_spec_absolute_time ("stamp_expire_withdraw", &stamp_expire_withdraw), + GNUNET_JSON_spec_absolute_time ("stamp_expire_deposit", + &stamp_expire_deposit), GNUNET_JSON_spec_absolute_time ("stamp_expire_legal", &stamp_expire_legal), GNUNET_JSON_spec_fixed_auto ("denom_secmod_sig", @@ -1739,7 +1857,7 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, &err_line)) { fprintf (stderr, - "Invalid input for signing key to 'show': %s#%u at %u (skipping)\n", + "Invalid input for denomination key to 'show': %s#%u at %u (skipping)\n", err_name, err_line, (unsigned int) index); @@ -1768,7 +1886,45 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, return GNUNET_SYSERR; } - // FIXME: print + { + char *withdraw_fee_s; + char *deposit_fee_s; + char *refresh_fee_s; + char *refund_fee_s; + char *deposit_s; + char *legal_s; + + withdraw_fee_s = TALER_amount_to_string (&fee_withdraw); + deposit_fee_s = TALER_amount_to_string (&fee_deposit); + refresh_fee_s = TALER_amount_to_string (&fee_refresh); + refund_fee_s = TALER_amount_to_string (&fee_refund); + deposit_s = GNUNET_strdup ( + GNUNET_STRINGS_absolute_time_to_string (stamp_expire_deposit)); + legal_s = GNUNET_strdup ( + GNUNET_STRINGS_absolute_time_to_string (stamp_expire_legal)); + + printf ( + "DENOMINATION-KEY(%s) %s of value %s starting at %s " + "(used for: %s, deposit until: %s legal end: %s) with fees %s/%s/%s/%s\n", + section_name, + TALER_B2S (&h_denom_pub), + TALER_amount2s (&coin_value), + GNUNET_STRINGS_absolute_time_to_string (stamp_start), + GNUNET_STRINGS_relative_time_to_string (duration, + GNUNET_NO), + deposit_s, + legal_s, + withdraw_fee_s, + deposit_fee_s, + refresh_fee_s, + refund_fee_s); + GNUNET_free (withdraw_fee_s); + GNUNET_free (deposit_fee_s); + GNUNET_free (refresh_fee_s); + GNUNET_free (refund_fee_s); + GNUNET_free (deposit_s); + GNUNET_free (legal_s); + } GNUNET_JSON_parse_free (spec); } @@ -1889,6 +2045,227 @@ do_show (char *const *args) } +/** + * Sign @a signkeys with offline key. + * + * @param secm_pub security module public key used to sign the denominations + * @param signkeys keys to output + * @param[in,out] result array where to output the signatures + * @return #GNUNET_OK on success + */ +static int +sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, + const json_t *signkeys, + json_t *result) +{ + size_t index; + json_t *value; + + json_array_foreach (signkeys, index, value) { + const char *err_name; + unsigned int err_line; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_SecurityModuleSignatureP secm_sig; + struct GNUNET_TIME_Absolute start_time; + struct GNUNET_TIME_Absolute sign_end; + struct GNUNET_TIME_Absolute legal_end; + struct GNUNET_TIME_Relative duration; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_absolute_time ("stamp_start", + &start_time), + GNUNET_JSON_spec_absolute_time ("stamp_expire", + &sign_end), + GNUNET_JSON_spec_absolute_time ("stamp_end", + &legal_end), + GNUNET_JSON_spec_fixed_auto ("key", + &exchange_pub), + GNUNET_JSON_spec_fixed_auto ("signkey_secmod_sig", + &secm_sig), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (value, + spec, + &err_name, + &err_line)) + { + fprintf (stderr, + "Invalid input for signing key to 'show': %s#%u at %u (skipping)\n", + err_name, + err_line, + (unsigned int) index); + global_ret = 7; + test_shutdown (); + return GNUNET_SYSERR; + } + + duration = GNUNET_TIME_absolute_get_difference (start_time, + sign_end); + if (GNUNET_OK != + TALER_exchange_secmod_eddsa_verify (&exchange_pub, + start_time, + duration, + secm_pub, + &secm_sig)) + { + fprintf (stderr, + "Invalid security module signature for key %s (aborting)\n", + TALER_B2S (&exchange_pub)); + global_ret = 9; + test_shutdown (); + return GNUNET_SYSERR; + } + { + struct TALER_MasterSignatureP master_sig; + + TALER_exchange_offline_signkey_validity_sign (&exchange_pub, + start_time, + sign_end, + legal_end, + &master_priv, + &master_sig); + GNUNET_assert (0 == + json_array_append_new ( + result, + json_pack ("{s:o,s:o}", + "exchange_pub", + GNUNET_JSON_from_data_auto (&exchange_pub), + "master_sig", + GNUNET_JSON_from_data_auto (&master_sig)))); + } + } + return GNUNET_OK; +} + + +/** + * Sign @a denomkeys with offline key. + * + * @param secm_pub security module public key used to sign the denominations + * @param denomkeys keys to output + * @param[in,out] result array where to output the signatures + * @return #GNUNET_OK on success + */ +static int +sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, + const json_t *denomkeys, + json_t *result) +{ + size_t index; + json_t *value; + + json_array_foreach (denomkeys, index, value) { + const char *err_name; + unsigned int err_line; + const char *section_name; + struct TALER_DenominationPublicKey denom_pub; + struct GNUNET_TIME_Absolute stamp_start; + struct GNUNET_TIME_Absolute stamp_expire_withdraw; + struct GNUNET_TIME_Absolute stamp_expire_deposit; + struct GNUNET_TIME_Absolute stamp_expire_legal; + struct TALER_Amount coin_value; + struct TALER_Amount fee_withdraw; + struct TALER_Amount fee_deposit; + struct TALER_Amount fee_refresh; + struct TALER_Amount fee_refund; + struct TALER_SecurityModuleSignatureP secm_sig; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_string ("section_name", + §ion_name), + GNUNET_JSON_spec_rsa_public_key ("denom_pub", + &denom_pub.rsa_public_key), + TALER_JSON_spec_amount ("value", + &coin_value), + TALER_JSON_spec_amount ("fee_withdraw", + &fee_withdraw), + TALER_JSON_spec_amount ("fee_deposit", + &fee_deposit), + TALER_JSON_spec_amount ("fee_refresh", + &fee_refresh), + TALER_JSON_spec_amount ("fee_refund", + &fee_refund), + GNUNET_JSON_spec_absolute_time ("stamp_start", + &stamp_start), + GNUNET_JSON_spec_absolute_time ("stamp_expire_withdraw", + &stamp_expire_withdraw), + GNUNET_JSON_spec_absolute_time ("stamp_expire_deposit", + &stamp_expire_deposit), + GNUNET_JSON_spec_absolute_time ("stamp_expire_legal", + &stamp_expire_legal), + GNUNET_JSON_spec_fixed_auto ("denom_secmod_sig", + &secm_sig), + GNUNET_JSON_spec_end () + }; + struct GNUNET_TIME_Relative duration; + struct GNUNET_HashCode h_denom_pub; + + if (GNUNET_OK != + GNUNET_JSON_parse (value, + spec, + &err_name, + &err_line)) + { + fprintf (stderr, + "Invalid input for denomination key to 'sign': %s#%u at %u (skipping)\n", + err_name, + err_line, + (unsigned int) index); + GNUNET_JSON_parse_free (spec); + global_ret = 7; + test_shutdown (); + return GNUNET_SYSERR; + } + duration = GNUNET_TIME_absolute_get_difference (stamp_start, + stamp_expire_withdraw); + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.rsa_public_key, + &h_denom_pub); + if (GNUNET_OK != + TALER_exchange_secmod_rsa_verify (&h_denom_pub, + section_name, + stamp_start, + duration, + secm_pub, + &secm_sig)) + { + fprintf (stderr, + "Invalid security module signature for key %s (aborting)\n", + TALER_B2S (&h_denom_pub)); + global_ret = 9; + test_shutdown (); + return GNUNET_SYSERR; + } + + { + struct TALER_MasterSignatureP master_sig; + + TALER_exchange_offline_denom_validity_sign (&h_denom_pub, + stamp_start, + stamp_expire_withdraw, + stamp_expire_deposit, + stamp_expire_legal, + &coin_value, + &fee_withdraw, + &fee_deposit, + &fee_refresh, + &fee_refund, + &master_priv, + &master_sig); + GNUNET_assert (0 == + json_array_append_new ( + result, + json_pack ("{s:o,s:o}", + "h_denomn_pub", + GNUNET_JSON_from_data_auto (&h_denom_pub), + "master_sig", + GNUNET_JSON_from_data_auto (&master_sig)))); + } + GNUNET_JSON_parse_free (spec); + } + return GNUNET_OK; +} + + /** * Sign future keys. * @@ -1918,10 +2295,94 @@ do_sign (char *const *args) } } + { + const char *err_name; + unsigned int err_line; + json_t *denomkeys; + json_t *signkeys; + struct TALER_MasterPublicKeyP mpub; + struct TALER_SecurityModulePublicKeyP secm[2]; + struct GNUNET_JSON_Specification spec[] = { + GNUNET_JSON_spec_json ("future_denoms", + &denomkeys), + GNUNET_JSON_spec_json ("future_signkeys", + &signkeys), + GNUNET_JSON_spec_fixed_auto ("master_pub", + &mpub), + GNUNET_JSON_spec_fixed_auto ("denom_secmod_public_key", + &secm[0]), + GNUNET_JSON_spec_fixed_auto ("signkey_secmod_public_key", + &secm[1]), + GNUNET_JSON_spec_end () + }; - // FIXME: do work here! + if (GNUNET_OK != + GNUNET_JSON_parse (in, + spec, + &err_name, + &err_line)) + { + fprintf (stderr, + "Invalid input to 'sign': %s#%u (skipping)\n", + err_name, + err_line); + global_ret = 7; + test_shutdown (); + return; + } + if (0 != + GNUNET_memcmp (&master_pub, + &mpub)) + { + fprintf (stderr, + "Fatal: exchange uses different master key!\n"); + global_ret = 6; + test_shutdown (); + GNUNET_JSON_parse_free (spec); + return; + } + if (GNUNET_SYSERR == + tofu_check (secm)) + { + fprintf (stderr, + "Fatal: security module keys changed!\n"); + global_ret = 8; + test_shutdown (); + GNUNET_JSON_parse_free (spec); + return; + } + { + json_t *signkey_sig_array = json_array (); + json_t *denomkey_sig_array = json_array (); + + GNUNET_assert (NULL != signkey_sig_array); + GNUNET_assert (NULL != denomkey_sig_array); + if ( (GNUNET_OK != + sign_signkeys (&secm[0], + signkeys, + signkey_sig_array)) || + (GNUNET_OK != + sign_denomkeys (&secm[1], + denomkeys, + denomkey_sig_array)) ) + { + global_ret = 8; + test_shutdown (); + json_decref (signkey_sig_array); + json_decref (denomkey_sig_array); + GNUNET_JSON_parse_free (spec); + return; + } - /* consume input */ + output_operation ("upload-keys", + json_pack ("{s:o, s:o}", + "denom_sigs", + denomkey_sig_array, + "signkey_sigs", + signkey_sig_array)); + } + GNUNET_JSON_parse_free (spec); + } json_decref (in); in = NULL; next (args); diff --git a/src/exchange/taler-exchange-httpd_management_post_keys.c b/src/exchange/taler-exchange-httpd_management_post_keys.c index 43ca5f8c4..cc52f5cf2 100644 --- a/src/exchange/taler-exchange-httpd_management_post_keys.c +++ b/src/exchange/taler-exchange-httpd_management_post_keys.c @@ -164,34 +164,20 @@ add_keys (void *cls, /* check signature is valid */ { - struct TALER_DenominationKeyValidityPS dkv = { - .purpose.purpose = htonl ( - TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY), - .purpose.size = htonl (sizeof (dkv)), - .master = TEH_master_public_key, - .start = GNUNET_TIME_absolute_hton (meta.start), - .expire_withdraw = GNUNET_TIME_absolute_hton (meta.expire_withdraw), - .expire_deposit = GNUNET_TIME_absolute_hton (meta.expire_deposit), - .expire_legal = GNUNET_TIME_absolute_hton (meta.expire_legal), - .denom_hash = akc->d_sigs[i].h_denom_pub - }; - - TALER_amount_hton (&dkv.value, - &meta.value); - TALER_amount_hton (&dkv.fee_withdraw, - &meta.fee_withdraw); - TALER_amount_hton (&dkv.fee_deposit, - &meta.fee_deposit); - TALER_amount_hton (&dkv.fee_refresh, - &meta.fee_refresh); - TALER_amount_hton (&dkv.fee_refund, - &meta.fee_refund); if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify ( - TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY, - &dkv, - &akc->d_sigs[i].master_sig.eddsa_signature, - &TEH_master_public_key.eddsa_pub)) + TALER_exchange_offline_denomkey_validity_verify ( + &akc->d_sigs[i].h_denom_pub, + meta.start, + meta.expire_withdraw, + meta.expire_deposit, + meta.expire_legal, + &meta.value, + &meta.fee_withdraw, + &meta.fee_deposit, + &meta.fee_refresh, + &meta.fee_refund, + &TEH_master_public_key, + &akc->d_sigs[i].master_sig)) { GNUNET_break_op (0); return TALER_MHD_reply_with_error ( diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index b6c7ac72c..757dee675 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1151,6 +1151,71 @@ TALER_exchange_offline_signkey_validity_verify ( const struct TALER_MasterSignatureP *master_sig); +/** + * Create denomination key validity signature. + * + * @param h_denom_pub hash of the denomination's public key + * @param stamp_start when does the exchange begin signing with this key + * @param stamp_expire_withdraw when does the exchange end signing with this key + * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key + * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key + * @param coin_value what is the value of coins signed with this key + * @param fee_withdraw what withdraw fee does the exchange charge for this denomination + * @param fee_deposit what deposit fee does the exchange charge for this denomination + * @param fee_refresh what refresh fee does the exchange charge for this denomination + * @param fee_refund what refund fee does the exchange charge for this denomination + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_denom_validity_sign ( + const struct GNUNET_HashCode *h_denom_pub, + struct GNUNET_TIME_Absolute stamp_start, + struct GNUNET_TIME_Absolute stamp_expire_withdraw, + struct GNUNET_TIME_Absolute stamp_expire_deposit, + struct GNUNET_TIME_Absolute stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_Amount *fee_withdraw, + const struct TALER_Amount *fee_deposit, + const struct TALER_Amount *fee_refresh, + const struct TALER_Amount *fee_refund, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify denomination key validity signature. + * + * @param h_denom_pub hash of the denomination's public key + * @param stamp_start when does the exchange begin signing with this key + * @param stamp_expire_withdraw when does the exchange end signing with this key + * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key + * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key + * @param coin_value what is the value of coins signed with this key + * @param fee_withdraw what withdraw fee does the exchange charge for this denomination + * @param fee_deposit what deposit fee does the exchange charge for this denomination + * @param fee_refresh what refresh fee does the exchange charge for this denomination + * @param fee_refund what refund fee does the exchange charge for this denomination + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +int +TALER_exchange_offline_denom_validity_verify ( + const struct GNUNET_HashCode *h_denom_pub, + struct GNUNET_TIME_Absolute stamp_start, + struct GNUNET_TIME_Absolute stamp_expire_withdraw, + struct GNUNET_TIME_Absolute stamp_expire_deposit, + struct GNUNET_TIME_Absolute stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_Amount *fee_withdraw, + const struct TALER_Amount *fee_deposit, + const struct TALER_Amount *fee_refresh, + const struct TALER_Amount *fee_refund, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + /** * Create security module EdDSA signature. * diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c index ed6093556..e630adf91 100644 --- a/src/lib/exchange_api_handle.c +++ b/src/lib/exchange_api_handle.c @@ -472,39 +472,21 @@ parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key, sizeof (struct GNUNET_HashCode)); if (! check_sigs) return GNUNET_OK; - { - struct TALER_DenominationKeyValidityPS denom_key_issue = { - .purpose.purpose - = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY), - .purpose.size = htonl (sizeof (denom_key_issue)), - .master = *master_key, - .denom_hash = denom_key->h_key, - .start = GNUNET_TIME_absolute_hton (denom_key->valid_from), - .expire_withdraw - = GNUNET_TIME_absolute_hton (denom_key->withdraw_valid_until), - .expire_deposit = GNUNET_TIME_absolute_hton (denom_key->expire_deposit), - .expire_legal = GNUNET_TIME_absolute_hton (denom_key->expire_legal) - }; - - TALER_amount_hton (&denom_key_issue.value, - &denom_key->value); - TALER_amount_hton (&denom_key_issue.fee_withdraw, - &denom_key->fee_withdraw); - TALER_amount_hton (&denom_key_issue.fee_deposit, - &denom_key->fee_deposit); - TALER_amount_hton (&denom_key_issue.fee_refresh, - &denom_key->fee_refresh); - TALER_amount_hton (&denom_key_issue.fee_refund, - &denom_key->fee_refund); - EXITIF (GNUNET_SYSERR == - GNUNET_CRYPTO_eddsa_verify ( - TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY, - &denom_key_issue, - &denom_key->master_sig.eddsa_signature, - &master_key->eddsa_pub)); - } + EXITIF (GNUNET_SYSERR == + TALER_exchange_offline_denom_validity_verify ( + &denom_key->h_key, + denom_key->valid_from, + denom_key->withdraw_valid_until, + denom_key->expire_deposit, + denom_key->expire_legal, + &denom_key->value, + &denom_key->fee_withdraw, + &denom_key->fee_deposit, + &denom_key->fee_refresh, + &denom_key->fee_refund, + master_key, + &denom_key->master_sig)); return GNUNET_OK; - EXITIF_exit: /* invalidate denom_key, just to be sure */ memset (denom_key, diff --git a/src/util/offline_signatures.c b/src/util/offline_signatures.c index af7876b93..d8f040321 100644 --- a/src/util/offline_signatures.c +++ b/src/util/offline_signatures.c @@ -155,6 +155,97 @@ TALER_exchange_offline_signkey_validity_verify ( } +void +TALER_exchange_offline_denom_validity_sign ( + const struct GNUNET_HashCode *h_denom_pub, + struct GNUNET_TIME_Absolute stamp_start, + struct GNUNET_TIME_Absolute stamp_expire_withdraw, + struct GNUNET_TIME_Absolute stamp_expire_deposit, + struct GNUNET_TIME_Absolute stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_Amount *fee_withdraw, + const struct TALER_Amount *fee_deposit, + const struct TALER_Amount *fee_refresh, + const struct TALER_Amount *fee_refund, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig) +{ + struct TALER_DenominationKeyValidityPS issue = { + .purpose.purpose + = htonl (TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY), + .purpose.size + = htonl (sizeof (issue)), + .start = GNUNET_TIME_absolute_hton (stamp_start), + .expire_withdraw = GNUNET_TIME_absolute_hton (stamp_expire_withdraw), + .expire_deposit = GNUNET_TIME_absolute_hton (stamp_expire_deposit), + .expire_legal = GNUNET_TIME_absolute_hton (stamp_expire_legal), + .denom_hash = *h_denom_pub + }; + + GNUNET_CRYPTO_eddsa_key_get_public (&master_priv->eddsa_priv, + &issue.master.eddsa_pub); + TALER_amount_hton (&issue.value, + coin_value); + TALER_amount_hton (&issue.fee_withdraw, + fee_withdraw); + TALER_amount_hton (&issue.fee_deposit, + fee_deposit); + TALER_amount_hton (&issue.fee_refresh, + fee_refresh); + TALER_amount_hton (&issue.fee_refund, + fee_refund); + GNUNET_CRYPTO_eddsa_sign (&master_priv->eddsa_priv, + &issue, + &master_sig->eddsa_signature); +} + + +int +TALER_exchange_offline_denom_validity_verify ( + const struct GNUNET_HashCode *h_denom_pub, + struct GNUNET_TIME_Absolute stamp_start, + struct GNUNET_TIME_Absolute stamp_expire_withdraw, + struct GNUNET_TIME_Absolute stamp_expire_deposit, + struct GNUNET_TIME_Absolute stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_Amount *fee_withdraw, + const struct TALER_Amount *fee_deposit, + const struct TALER_Amount *fee_refresh, + const struct TALER_Amount *fee_refund, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig) +{ + struct TALER_DenominationKeyValidityPS dkv = { + .purpose.purpose = htonl ( + TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY), + .purpose.size = htonl (sizeof (dkv)), + .master = *master_pub, + .start = GNUNET_TIME_absolute_hton (stamp_start), + .expire_withdraw = GNUNET_TIME_absolute_hton (stamp_expire_withdraw), + .expire_deposit = GNUNET_TIME_absolute_hton (stamp_expire_deposit), + .expire_legal = GNUNET_TIME_absolute_hton (stamp_expire_legal), + .denom_hash = *h_denom_pub + }; + + TALER_amount_hton (&dkv.value, + coin_value); + TALER_amount_hton (&dkv.fee_withdraw, + fee_withdraw); + TALER_amount_hton (&dkv.fee_deposit, + fee_deposit); + TALER_amount_hton (&dkv.fee_refresh, + fee_refresh); + TALER_amount_hton (&dkv.fee_refund, + fee_refund); + return + GNUNET_CRYPTO_eddsa_verify ( + TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY, + &dkv, + &master_sig->eddsa_signature, + &master_pub->eddsa_pub); +} + + void TALER_exchange_offline_wire_add_sign ( const char *payto_uri, -- cgit v1.2.3