From b61f601028f38a6c56aa00f171fa20605ca8c663 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 17 Nov 2021 23:02:05 +0100 Subject: -use different hash for RSA vs. Denomination hashing --- src/exchange-tools/taler-exchange-offline.c | 69 +++- src/exchange/taler-exchange-httpd_keys.c | 107 ++++- src/include/taler_crypto_lib.h | 73 ++-- src/include/taler_signatures.h | 6 +- src/lib/exchange_api_management_get_keys.c | 31 +- src/util/Makefile.am | 2 +- src/util/crypto_helper_denom.c | 610 ---------------------------- src/util/crypto_helper_rsa.c | 610 ++++++++++++++++++++++++++++ src/util/denom.c | 16 + src/util/secmod_signatures.c | 18 +- src/util/taler-exchange-secmod-rsa.c | 52 +-- src/util/taler-exchange-secmod-rsa.h | 12 +- 12 files changed, 883 insertions(+), 723 deletions(-) delete mode 100644 src/util/crypto_helper_denom.c create mode 100644 src/util/crypto_helper_rsa.c (limited to 'src') diff --git a/src/exchange-tools/taler-exchange-offline.c b/src/exchange-tools/taler-exchange-offline.c index 891177581..e6ef0fc2c 100644 --- a/src/exchange-tools/taler-exchange-offline.c +++ b/src/exchange-tools/taler-exchange-offline.c @@ -2635,6 +2635,7 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, }; struct GNUNET_TIME_Relative duration; struct TALER_DenominationHash h_denom_pub; + enum GNUNET_GenericReturnValue ok; if (GNUNET_OK != GNUNET_JSON_parse (value, @@ -2659,13 +2660,28 @@ show_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, stamp_expire_withdraw); TALER_denom_pub_hash (&denom_pub, &h_denom_pub); - if (GNUNET_OK != - TALER_exchange_secmod_denom_verify (&h_denom_pub, - section_name, - stamp_start, - duration, - secm_pub, - &secm_sig)) + switch (denom_pub.cipher) + { + case TALER_DENOMINATION_RSA: + { + struct TALER_RsaPubHashP h_rsa; + + TALER_rsa_pub_hash (denom_pub.details.rsa_public_key, + &h_rsa); + ok = TALER_exchange_secmod_rsa_verify (&h_rsa, + section_name, + stamp_start, + duration, + secm_pub, + &secm_sig); + } + break; + default: + GNUNET_break (0); + ok = GNUNET_SYSERR; + break; + } + if (GNUNET_OK != ok) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Invalid security module signature for denomination key %s (aborting)\n", @@ -2997,7 +3013,7 @@ sign_signkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, * @param[in,out] result array where to output the signatures * @return #GNUNET_OK on success */ -static int +static enum GNUNET_GenericReturnValue sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, const json_t *denomkeys, json_t *result) @@ -3076,19 +3092,36 @@ sign_denomkeys (const struct TALER_SecurityModulePublicKeyP *secm_pub, } duration = GNUNET_TIME_absolute_get_difference (stamp_start, stamp_expire_withdraw); + // FIXME-Oec: setup age mask here? TALER_denom_pub_hash (&denom_pub, &h_denom_pub); - if (GNUNET_OK != - TALER_exchange_secmod_denom_verify (&h_denom_pub, - section_name, - stamp_start, - duration, - secm_pub, - &secm_sig)) + switch (denom_pub.cipher) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Invalid security module signature for denomination key %s (aborting)\n", - GNUNET_h2s (&h_denom_pub.hash)); + case TALER_DENOMINATION_RSA: + { + struct TALER_RsaPubHashP h_rsa; + + TALER_rsa_pub_hash (denom_pub.details.rsa_public_key, + &h_rsa); + if (GNUNET_OK != + TALER_exchange_secmod_rsa_verify (&h_rsa, + section_name, + stamp_start, + duration, + secm_pub, + &secm_sig)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Invalid security module signature for denomination key %s (aborting)\n", + GNUNET_h2s (&h_denom_pub.hash)); + global_ret = EXIT_FAILURE; + test_shutdown (); + GNUNET_JSON_parse_free (spec); + return GNUNET_SYSERR; + } + } + break; + default: global_ret = EXIT_FAILURE; test_shutdown (); GNUNET_JSON_parse_free (spec); diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c index e094f273f..f09f61c0e 100644 --- a/src/exchange/taler-exchange-httpd_keys.c +++ b/src/exchange/taler-exchange-httpd_keys.c @@ -71,7 +71,7 @@ struct HelperDenomination struct GNUNET_TIME_Relative validity_duration; /** - * Hash of the denomination key. + * Hash of the full denomination key. */ struct TALER_DenominationHash h_denom_pub; @@ -85,11 +85,25 @@ struct HelperDenomination */ struct TALER_DenominationPublicKey denom_pub; + /** + * Details depend on the @e denom_pub.cipher type. + */ + union + { + + /** + * Hash of the RSA key. + */ + struct TALER_RsaPubHashP h_rsa; + + } h_details; + /** * Name in configuration section for this denomination type. */ char *section_name; + }; @@ -167,13 +181,18 @@ struct HelperState /** * Handle for the denom/RSA helper. */ - struct TALER_CRYPTO_DenominationHelper *dh; + struct TALER_CRYPTO_RsaDenominationHelper *dh; /** * Map from H(denom_pub) to `struct HelperDenomination` entries. */ struct GNUNET_CONTAINER_MultiHashMap *denom_keys; + /** + * Map from H(rsa_pub) to `struct HelperDenomination` entries. + */ + struct GNUNET_CONTAINER_MultiHashMap *rsa_keys; + /** * Map from `struct TALER_ExchangePublicKey` to `struct HelperSignkey` * entries. Based on the fact that a `struct GNUNET_PeerIdentity` is also @@ -591,6 +610,8 @@ destroy_key_helpers (struct HelperState *hs) GNUNET_CONTAINER_multihashmap_iterate (hs->denom_keys, &free_denom_cb, hs); + GNUNET_CONTAINER_multihashmap_destroy (hs->rsa_keys); + hs->rsa_keys = NULL; GNUNET_CONTAINER_multihashmap_destroy (hs->denom_keys); hs->denom_keys = NULL; GNUNET_CONTAINER_multipeermap_iterate (hs->esign_keys, @@ -600,7 +621,7 @@ destroy_key_helpers (struct HelperState *hs) hs->esign_keys = NULL; if (NULL != hs->dh) { - TALER_CRYPTO_helper_denom_disconnect (hs->dh); + TALER_CRYPTO_helper_rsa_disconnect (hs->dh); hs->dh = NULL; } if (NULL != hs->esh) @@ -630,12 +651,12 @@ destroy_key_helpers (struct HelperState *hs) * The signature was already verified against @a sm_pub. */ static void -helper_denom_cb ( +helper_rsa_cb ( void *cls, const char *section_name, struct GNUNET_TIME_Absolute start_time, struct GNUNET_TIME_Relative validity_duration, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_RsaPubHashP *h_rsa, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_SecurityModulePublicKeyP *sm_pub, const struct TALER_SecurityModuleSignatureP *sm_sig) @@ -645,14 +666,14 @@ helper_denom_cb ( GNUNET_log (GNUNET_ERROR_TYPE_INFO, "RSA helper announces key %s for denomination type %s with validity %s\n", - GNUNET_h2s (&h_denom_pub->hash), + GNUNET_h2s (&h_rsa->hash), section_name, GNUNET_STRINGS_relative_time_to_string (validity_duration, GNUNET_NO)); key_generation++; TEH_resume_keys_requests (false); - hd = GNUNET_CONTAINER_multihashmap_get (hs->denom_keys, - &h_denom_pub->hash); + hd = GNUNET_CONTAINER_multihashmap_get (hs->rsa_keys, + &h_rsa->hash); if (NULL != hd) { /* should be just an update (revocation!), so update existing entry */ @@ -664,10 +685,19 @@ helper_denom_cb ( hd = GNUNET_new (struct HelperDenomination); hd->start_time = start_time; hd->validity_duration = validity_duration; - hd->h_denom_pub = *h_denom_pub; + hd->h_details.h_rsa = *h_rsa; hd->sm_sig = *sm_sig; TALER_denom_pub_deep_copy (&hd->denom_pub, denom_pub); + // FIXME-OEC: set AGE RESTRICTION (from 'global' variable, + // that itself is set from /managmenet API!) HERE! + // ISSUE: tricky to handle if configuration changes + // between denominations (some with/without age + // restrictions). For that, we probably need to look at + // configuration [$section_name] (!?). + hd->denom_pub.age_mask.mask = 0; + TALER_denom_pub_hash (&hd->denom_pub, + &hd->h_denom_pub); hd->section_name = GNUNET_strdup (section_name); GNUNET_assert ( GNUNET_OK == @@ -676,6 +706,13 @@ helper_denom_cb ( &hd->h_denom_pub.hash, hd, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); + GNUNET_assert ( + GNUNET_OK == + GNUNET_CONTAINER_multihashmap_put ( + hs->rsa_keys, + &hd->h_details.h_rsa.hash, + hd, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)); } @@ -752,12 +789,15 @@ setup_key_helpers (struct HelperState *hs) hs->denom_keys = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES); + hs->rsa_keys + = GNUNET_CONTAINER_multihashmap_create (1024, + GNUNET_YES); hs->esign_keys = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_NO /* MUST BE NO! */); - hs->dh = TALER_CRYPTO_helper_denom_connect (TEH_cfg, - &helper_denom_cb, - hs); + hs->dh = TALER_CRYPTO_helper_rsa_connect (TEH_cfg, + &helper_rsa_cb, + hs); if (NULL == hs->dh) { destroy_key_helpers (hs); @@ -783,7 +823,7 @@ setup_key_helpers (struct HelperState *hs) static void sync_key_helpers (struct HelperState *hs) { - TALER_CRYPTO_helper_denom_poll (hs->dh); + TALER_CRYPTO_helper_rsa_poll (hs->dh); TALER_CRYPTO_helper_esign_poll (hs->esh); } @@ -1925,6 +1965,7 @@ TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub, { struct TEH_KeyStateHandle *ksh; struct TALER_BlindedDenominationSignature none; + struct HelperDenomination *hd; memset (&none, 0, @@ -1935,11 +1976,25 @@ TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub, *ec = TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING; return none; } - return TALER_CRYPTO_helper_denom_sign (ksh->helpers->dh, - h_denom_pub, + hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys, + &h_denom_pub->hash); + if (NULL == hd) + { + *ec = TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; + return none; + } + switch (hd->denom_pub.cipher) + { + case TALER_DENOMINATION_RSA: + return TALER_CRYPTO_helper_rsa_sign (ksh->helpers->dh, + &hd->h_details.h_rsa, msg, msg_size, ec); + default: + *ec = TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + return none; + } } @@ -1947,6 +2002,7 @@ void TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub) { struct TEH_KeyStateHandle *ksh; + struct HelperDenomination *hd; ksh = TEH_keys_get_state (); if (NULL == ksh) @@ -1954,9 +2010,24 @@ TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub) GNUNET_break (0); return; } - TALER_CRYPTO_helper_denom_revoke (ksh->helpers->dh, - h_denom_pub); - TEH_keys_update_states (); + hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys, + &h_denom_pub->hash); + if (NULL == hd) + { + GNUNET_break (0); + return; + } + switch (hd->denom_pub.cipher) + { + case TALER_DENOMINATION_RSA: + TALER_CRYPTO_helper_rsa_revoke (ksh->helpers->dh, + &hd->h_details.h_rsa); + TEH_keys_update_states (); + return; + default: + GNUNET_break (0); + return; + } } diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 0a40282e1..ea53efb66 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -402,6 +402,31 @@ struct TALER_WireSalt }; +/** + * Hash used to represent an RSA public key. Does not include age + * restrictions and is ONLY for RSA. Used ONLY for interactions with the RSA + * security module. + */ +struct TALER_RsaPubHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Hash @a rsa. + * + * @param rsa key to hash + * @param[out] h_rsa where to write the result + */ +void +TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa, + struct TALER_RsaPubHashP *h_rsa); + + /** * Hash used to represent a denomination public key * and associated age restrictions (if any). @@ -1318,7 +1343,7 @@ TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, /** * Handle for talking to an Denomination key signing helper. */ -struct TALER_CRYPTO_DenominationHelper; +struct TALER_CRYPTO_RsaDenominationHelper; /** * Function called with information about available keys for signing. Usually @@ -1332,19 +1357,19 @@ struct TALER_CRYPTO_DenominationHelper; * 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_denom_pub hash of the @a denom_pub that is available (or was purged) + * @param h_rsa hash of the RSA @a denom_pub that is available (or was purged) * @param denom_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 -(*TALER_CRYPTO_DenominationKeyStatusCallback)( +(*TALER_CRYPTO_RsaDenominationKeyStatusCallback)( void *cls, const char *section_name, struct GNUNET_TIME_Absolute start_time, struct GNUNET_TIME_Relative validity_duration, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_RsaPubHashP *h_rsa, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_SecurityModulePublicKeyP *sm_pub, const struct TALER_SecurityModuleSignatureP *sm_sig); @@ -1358,10 +1383,10 @@ typedef void * @param dkc_cls closure for @a dkc * @return NULL on error (such as bad @a cfg). */ -struct TALER_CRYPTO_DenominationHelper * -TALER_CRYPTO_helper_denom_connect ( +struct TALER_CRYPTO_RsaDenominationHelper * +TALER_CRYPTO_helper_rsa_connect ( const struct GNUNET_CONFIGURATION_Handle *cfg, - TALER_CRYPTO_DenominationKeyStatusCallback dkc, + TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc, void *dkc_cls); @@ -1375,7 +1400,7 @@ TALER_CRYPTO_helper_denom_connect ( * @param dh helper process connection */ void -TALER_CRYPTO_helper_denom_poll (struct TALER_CRYPTO_DenominationHelper *dh); +TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *dh); /** @@ -1389,7 +1414,7 @@ TALER_CRYPTO_helper_denom_poll (struct TALER_CRYPTO_DenominationHelper *dh); * differences in the signature counters. Retrying in this case may work. * * @param dh helper process connection - * @param h_denom_pub hash of the public key to use to sign + * @param h_rsa hash of the RSA public key to use to sign * @param msg message to sign * @param msg_size number of bytes in @a msg * @param[out] ec set to the error code (or #TALER_EC_NONE on success) @@ -1397,9 +1422,9 @@ TALER_CRYPTO_helper_denom_poll (struct TALER_CRYPTO_DenominationHelper *dh); * see @a ec for details about the failure */ struct TALER_BlindedDenominationSignature -TALER_CRYPTO_helper_denom_sign ( - struct TALER_CRYPTO_DenominationHelper *dh, - const struct TALER_DenominationHash *h_denom_pub, +TALER_CRYPTO_helper_rsa_sign ( + struct TALER_CRYPTO_RsaDenominationHelper *dh, + const struct TALER_RsaPubHashP *h_rsa, const void *msg, size_t msg_size, enum TALER_ErrorCode *ec); @@ -1418,12 +1443,12 @@ TALER_CRYPTO_helper_denom_sign ( * callback. * * @param dh helper to process connection - * @param h_denom_pub hash of the public key to revoke + * @param h_rsa hash of the RSA public key to revoke */ void -TALER_CRYPTO_helper_denom_revoke ( - struct TALER_CRYPTO_DenominationHelper *dh, - const struct TALER_DenominationHash *h_denom_pub); +TALER_CRYPTO_helper_rsa_revoke ( + struct TALER_CRYPTO_RsaDenominationHelper *dh, + const struct TALER_RsaPubHashP *h_rsa); /** @@ -1432,8 +1457,8 @@ TALER_CRYPTO_helper_denom_revoke ( * @param[in] dh connection to close */ void -TALER_CRYPTO_helper_denom_disconnect ( - struct TALER_CRYPTO_DenominationHelper *dh); +TALER_CRYPTO_helper_rsa_disconnect ( + struct TALER_CRYPTO_RsaDenominationHelper *dh); /** @@ -1990,7 +2015,7 @@ TALER_exchange_secmod_eddsa_verify ( /** * Create security module denomination signature. * - * @param h_denom_pub hash of the public key to sign + * @param h_rsa hash of the RSA public key to sign * @param section_name name of the section in the configuration * @param start_sign starting point of validity for signing * @param duration how long will the key be in use @@ -1998,8 +2023,8 @@ TALER_exchange_secmod_eddsa_verify ( * @param[out] secm_sig where to write the signature */ void -TALER_exchange_secmod_denom_sign ( - const struct TALER_DenominationHash *h_denom_pub, +TALER_exchange_secmod_rsa_sign ( + const struct TALER_RsaPubHashP *h_rsa, const char *section_name, struct GNUNET_TIME_Absolute start_sign, struct GNUNET_TIME_Relative duration, @@ -2010,7 +2035,7 @@ TALER_exchange_secmod_denom_sign ( /** * Verify security module denomination signature. * - * @param h_denom_pub hash of the public key to validate + * @param h_rsa hash of the public key to validate * @param section_name name of the section in the configuration * @param start_sign starting point of validity for signing * @param duration how long will the key be in use @@ -2019,8 +2044,8 @@ TALER_exchange_secmod_denom_sign ( * @return #GNUNET_OK if the signature is valid */ enum GNUNET_GenericReturnValue -TALER_exchange_secmod_denom_verify ( - const struct TALER_DenominationHash *h_denom_pub, +TALER_exchange_secmod_rsa_verify ( + const struct TALER_RsaPubHashP *h_rsa, const char *section_name, struct GNUNET_TIME_Absolute start_sign, struct GNUNET_TIME_Relative duration, diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 40755348d..991c56e65 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -271,7 +271,7 @@ /** * Signature on a denomination key announcement. */ -#define TALER_SIGNATURE_SM_DENOMINATION_KEY 1250 +#define TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY 1250 /** * Signature on an exchange message signing key announcement. @@ -324,7 +324,7 @@ struct TALER_DenominationKeyAnnouncementPS { /** - * Purpose must be #TALER_SIGNATURE_SM_DENOMINATION_KEY. + * Purpose must be #TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY. * Used with an EdDSA signature of a `struct TALER_SecurityModulePublicKeyP`. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; @@ -332,7 +332,7 @@ struct TALER_DenominationKeyAnnouncementPS /** * Hash of the denomination public key. */ - struct TALER_DenominationHash h_denom_pub; + struct TALER_RsaPubHashP h_rsa; /** * Hash of the section name in the configuration of this denomination. diff --git a/src/lib/exchange_api_management_get_keys.c b/src/lib/exchange_api_management_get_keys.c index 980836792..5e6024f27 100644 --- a/src/lib/exchange_api_management_get_keys.c +++ b/src/lib/exchange_api_management_get_keys.c @@ -219,20 +219,37 @@ handle_ok (struct TALER_EXCHANGE_ManagementGetKeysHandle *gh, TALER_denom_pub_hash (&denom_key->key, &h_denom_pub); - if (GNUNET_OK != - TALER_exchange_secmod_denom_verify (&h_denom_pub, - section_name, - denom_key->valid_from, - duration, - &fk.denom_secmod_public_key, - &denom_key->denom_secmod_sig)) + switch (denom_key->key.cipher) { + case TALER_DENOMINATION_RSA: + { + struct TALER_RsaPubHashP h_rsa; + + TALER_rsa_pub_hash (denom_key->key.details.rsa_public_key, + &h_rsa); + if (GNUNET_OK != + TALER_exchange_secmod_rsa_verify (&h_rsa, + section_name, + denom_key->valid_from, + duration, + &fk.denom_secmod_public_key, + &denom_key->denom_secmod_sig)) + { + GNUNET_break_op (0); + ok = false; + break; + } + } + break; + default: GNUNET_break_op (0); ok = false; break; } } GNUNET_JSON_parse_free (spec); + if (! ok) + break; } if (ok) { diff --git a/src/util/Makefile.am b/src/util/Makefile.am index eefdcef45..7f2a2314d 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -79,7 +79,7 @@ libtalerutil_la_SOURCES = \ config.c \ crypto.c \ crypto_helper_common.c \ - crypto_helper_denom.c \ + crypto_helper_rsa.c \ crypto_helper_esign.c \ crypto_wire.c \ denom.c \ diff --git a/src/util/crypto_helper_denom.c b/src/util/crypto_helper_denom.c deleted file mode 100644 index 5aa60a24f..000000000 --- a/src/util/crypto_helper_denom.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - 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 -*/ -/** - * @file util/crypto_helper_denom.c - * @brief utility functions for running out-of-process private key operations - * @author Christian Grothoff - */ -#include "platform.h" -#include "taler_util.h" -#include "taler_signatures.h" -#include "taler-exchange-secmod-rsa.h" -#include -#include "crypto_helper_common.h" - - -struct TALER_CRYPTO_DenominationHelper -{ - /** - * Function to call with updates to available key material. - */ - TALER_CRYPTO_DenominationKeyStatusCallback 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 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 TALER_CRYPTO_DenominationHelper *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 TALER_CRYPTO_DenominationHelper *dh) -{ - if (-1 != dh->sock) - return GNUNET_OK; - 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; - } - return GNUNET_OK; -} - - -struct TALER_CRYPTO_DenominationHelper * -TALER_CRYPTO_helper_denom_connect ( - const struct GNUNET_CONFIGURATION_Handle *cfg, - TALER_CRYPTO_DenominationKeyStatusCallback dkc, - void *dkc_cls) -{ - struct TALER_CRYPTO_DenominationHelper *dh; - char *unixpath; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, - "taler-exchange-secmod-rsa", - "UNIXPATH", - &unixpath)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "taler-exchange-secmod-rsa", - "UNIXPATH"); - 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); - return NULL; - } - dh = GNUNET_new (struct TALER_CRYPTO_DenominationHelper); - 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)) - { - TALER_CRYPTO_helper_denom_disconnect (dh); - return NULL; - } - TALER_CRYPTO_helper_denom_poll (dh); - 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 TALER_CRYPTO_DenominationHelper *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; - - if (sizeof (*kan) > ntohs (hdr->size)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - if (ntohs (hdr->size) != - sizeof (*kan) - + ntohs (kan->pub_size) - + ntohs (kan->section_name_len)) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - section_name = &buf[ntohs (kan->pub_size)]; - if ('\0' != section_name[ntohs (kan->section_name_len) - 1]) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - - { - struct TALER_DenominationPublicKey denom_pub; - struct TALER_DenominationHash h_denom_pub; - - denom_pub.cipher = TALER_DENOMINATION_RSA; - denom_pub.details.rsa_public_key - = GNUNET_CRYPTO_rsa_public_key_decode (buf, - ntohs (kan->pub_size)); - if (NULL == denom_pub.details.rsa_public_key) - { - GNUNET_break_op (0); - return GNUNET_SYSERR; - } - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.details.rsa_public_key, - &h_denom_pub.hash); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received RSA key %s (%s)\n", - GNUNET_h2s (&h_denom_pub.hash), - section_name); - if (GNUNET_OK != - TALER_exchange_secmod_denom_verify ( - &h_denom_pub, - section_name, - GNUNET_TIME_absolute_ntoh (kan->anchor_time), - GNUNET_TIME_relative_ntoh (kan->duration_withdraw), - &kan->secm_pub, - &kan->secm_sig)) - { - GNUNET_break_op (0); - TALER_denom_pub_free (&denom_pub); - return GNUNET_SYSERR; - } - dh->dkc (dh->dkc_cls, - section_name, - GNUNET_TIME_absolute_ntoh (kan->anchor_time), - GNUNET_TIME_relative_ntoh (kan->duration_withdraw), - &h_denom_pub, - &denom_pub, - &kan->secm_pub, - &kan->secm_sig); - TALER_denom_pub_free (&denom_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 TALER_CRYPTO_DenominationHelper *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 denomination key %s\n", - GNUNET_h2s (&pn->h_denom_pub.hash)); - dh->dkc (dh->dkc_cls, - NULL, - GNUNET_TIME_UNIT_ZERO_ABS, - GNUNET_TIME_UNIT_ZERO, - &pn->h_denom_pub, - NULL, - NULL, - NULL); - return GNUNET_OK; -} - - -void -TALER_CRYPTO_helper_denom_poll (struct TALER_CRYPTO_DenominationHelper *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, - sizeof (buf), - (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; - 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; - } -} - - -struct TALER_BlindedDenominationSignature -TALER_CRYPTO_helper_denom_sign ( - struct TALER_CRYPTO_DenominationHelper *dh, - const struct TALER_DenominationHash *h_denom_pub, - const void *msg, - size_t msg_size, - enum TALER_ErrorCode *ec) -{ - struct TALER_BlindedDenominationSignature ds = { - .cipher = TALER_DENOMINATION_INVALID - }; - - if (GNUNET_OK != - try_connect (dh)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Failed to connect to helper\n"); - *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; - return ds; - } - - { - char buf[sizeof (struct TALER_CRYPTO_SignRequest) + 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_denom_pub = *h_denom_pub; - memcpy (&sr[1], - msg, - 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); - *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; - return ds; - } - } - - { - char buf[UINT16_MAX]; - size_t off = 0; - const struct GNUNET_MessageHeader *hdr - = (const struct GNUNET_MessageHeader *) buf; - bool finished = false; - - *ec = TALER_EC_INVALID; - while (1) - { - uint16_t msize; - ssize_t ret; - - ret = recv (dh->sock, - buf, - sizeof (buf), - (finished && (0 == off)) - ? MSG_DONTWAIT - : 0); - if (ret < 0) - { - if (EINTR == errno) - continue; - if (EAGAIN == errno) - { - GNUNET_assert (finished); - GNUNET_assert (0 == off); - return ds; - } - 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 ds; - } - 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)) || - (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; - - 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; - } - *ec = TALER_EC_NONE; - finished = true; - ds.cipher = TALER_DENOMINATION_RSA; - ds.details.blinded_rsa_signature = rsa_signature; - 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); - return ds; - } - case TALER_HELPER_RSA_MT_AVAIL: - 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: - 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) - TALER_blinded_denom_sig_free (&ds); - return ds; - } -} - - -void -TALER_CRYPTO_helper_denom_revoke ( - struct TALER_CRYPTO_DenominationHelper *dh, - const struct TALER_DenominationHash *h_denom_pub) -{ - struct TALER_CRYPTO_RevokeRequest rr = { - .header.size = htons (sizeof (rr)), - .header.type = htons (TALER_HELPER_RSA_MT_REQ_REVOKE), - .h_denom_pub = *h_denom_pub - }; - - 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 denomination key %s\n", - GNUNET_h2s (&h_denom_pub->hash)); -} - - -void -TALER_CRYPTO_helper_denom_disconnect ( - struct TALER_CRYPTO_DenominationHelper *dh) -{ - if (-1 != dh->sock) - do_disconnect (dh); - GNUNET_free (dh); -} - - -/* end of crypto_helper_denom.c */ diff --git a/src/util/crypto_helper_rsa.c b/src/util/crypto_helper_rsa.c new file mode 100644 index 000000000..8c3be457f --- /dev/null +++ b/src/util/crypto_helper_rsa.c @@ -0,0 +1,610 @@ +/* + 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 +*/ +/** + * @file util/crypto_helper_denom.c + * @brief utility functions for running out-of-process private key operations + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler_util.h" +#include "taler_signatures.h" +#include "taler-exchange-secmod-rsa.h" +#include +#include "crypto_helper_common.h" + + +struct TALER_CRYPTO_RsaDenominationHelper +{ + /** + * Function to call with updates to available key material. + */ + TALER_CRYPTO_RsaDenominationKeyStatusCallback 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 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 TALER_CRYPTO_RsaDenominationHelper *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 TALER_CRYPTO_RsaDenominationHelper *dh) +{ + if (-1 != dh->sock) + return GNUNET_OK; + 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; + } + return GNUNET_OK; +} + + +struct TALER_CRYPTO_RsaDenominationHelper * +TALER_CRYPTO_helper_rsa_connect ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc, + void *dkc_cls) +{ + struct TALER_CRYPTO_RsaDenominationHelper *dh; + char *unixpath; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_filename (cfg, + "taler-exchange-secmod-rsa", + "UNIXPATH", + &unixpath)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "taler-exchange-secmod-rsa", + "UNIXPATH"); + 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); + return NULL; + } + dh = GNUNET_new (struct TALER_CRYPTO_RsaDenominationHelper); + 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)) + { + TALER_CRYPTO_helper_rsa_disconnect (dh); + return NULL; + } + TALER_CRYPTO_helper_rsa_poll (dh); + 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 TALER_CRYPTO_RsaDenominationHelper *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; + + if (sizeof (*kan) > ntohs (hdr->size)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + if (ntohs (hdr->size) != + sizeof (*kan) + + ntohs (kan->pub_size) + + ntohs (kan->section_name_len)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + section_name = &buf[ntohs (kan->pub_size)]; + if ('\0' != section_name[ntohs (kan->section_name_len) - 1]) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + + { + struct TALER_DenominationPublicKey denom_pub; + struct TALER_RsaPubHashP h_rsa; + + denom_pub.cipher = TALER_DENOMINATION_RSA; + denom_pub.details.rsa_public_key + = GNUNET_CRYPTO_rsa_public_key_decode (buf, + ntohs (kan->pub_size)); + if (NULL == denom_pub.details.rsa_public_key) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub.details.rsa_public_key, + &h_rsa.hash); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received RSA key %s (%s)\n", + GNUNET_h2s (&h_rsa.hash), + section_name); + if (GNUNET_OK != + TALER_exchange_secmod_rsa_verify ( + &h_rsa, + section_name, + GNUNET_TIME_absolute_ntoh (kan->anchor_time), + GNUNET_TIME_relative_ntoh (kan->duration_withdraw), + &kan->secm_pub, + &kan->secm_sig)) + { + GNUNET_break_op (0); + TALER_denom_pub_free (&denom_pub); + return GNUNET_SYSERR; + } + dh->dkc (dh->dkc_cls, + section_name, + GNUNET_TIME_absolute_ntoh (kan->anchor_time), + GNUNET_TIME_relative_ntoh (kan->duration_withdraw), + &h_rsa, + &denom_pub, + &kan->secm_pub, + &kan->secm_sig); + TALER_denom_pub_free (&denom_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 TALER_CRYPTO_RsaDenominationHelper *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 denomination key %s\n", + GNUNET_h2s (&pn->h_rsa.hash)); + dh->dkc (dh->dkc_cls, + NULL, + GNUNET_TIME_UNIT_ZERO_ABS, + GNUNET_TIME_UNIT_ZERO, + &pn->h_rsa, + NULL, + NULL, + NULL); + return GNUNET_OK; +} + + +void +TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *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, + sizeof (buf), + (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; + 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; + } +} + + +struct TALER_BlindedDenominationSignature +TALER_CRYPTO_helper_rsa_sign ( + struct TALER_CRYPTO_RsaDenominationHelper *dh, + const struct TALER_RsaPubHashP *h_rsa, + const void *msg, + size_t msg_size, + enum TALER_ErrorCode *ec) +{ + struct TALER_BlindedDenominationSignature ds = { + .cipher = TALER_DENOMINATION_INVALID + }; + + if (GNUNET_OK != + try_connect (dh)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Failed to connect to helper\n"); + *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; + return ds; + } + + { + char buf[sizeof (struct TALER_CRYPTO_SignRequest) + 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 = *h_rsa; + memcpy (&sr[1], + msg, + 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); + *ec = TALER_EC_EXCHANGE_DENOMINATION_HELPER_UNAVAILABLE; + return ds; + } + } + + { + char buf[UINT16_MAX]; + size_t off = 0; + const struct GNUNET_MessageHeader *hdr + = (const struct GNUNET_MessageHeader *) buf; + bool finished = false; + + *ec = TALER_EC_INVALID; + while (1) + { + uint16_t msize; + ssize_t ret; + + ret = recv (dh->sock, + buf, + sizeof (buf), + (finished && (0 == off)) + ? MSG_DONTWAIT + : 0); + if (ret < 0) + { + if (EINTR == errno) + continue; + if (EAGAIN == errno) + { + GNUNET_assert (finished); + GNUNET_assert (0 == off); + return ds; + } + 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 ds; + } + 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)) || + (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; + + 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; + } + *ec = TALER_EC_NONE; + finished = true; + ds.cipher = TALER_DENOMINATION_RSA; + ds.details.blinded_rsa_signature = rsa_signature; + 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); + return ds; + } + case TALER_HELPER_RSA_MT_AVAIL: + 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: + 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) + TALER_blinded_denom_sig_free (&ds); + return ds; + } +} + + +void +TALER_CRYPTO_helper_rsa_revoke ( + struct TALER_CRYPTO_RsaDenominationHelper *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 denomination key %s\n", + GNUNET_h2s (&h_rsa->hash)); +} + + +void +TALER_CRYPTO_helper_rsa_disconnect ( + struct TALER_CRYPTO_RsaDenominationHelper *dh) +{ + if (-1 != dh->sock) + do_disconnect (dh); + GNUNET_free (dh); +} + + +/* end of crypto_helper_denom.c */ diff --git a/src/util/denom.c b/src/util/denom.c index bb1351406..b6b3764da 100644 --- a/src/util/denom.c +++ b/src/util/denom.c @@ -156,6 +156,22 @@ TALER_blinding_secret_create (union TALER_DenominationBlindingKeyP *bs) } +/** + * Hash @a rsa. + * + * @param rsa key to hash + * @param[out] h_rsa where to write the result + */ +void +TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa, + struct TALER_RsaPubHashP *h_rsa) +{ + GNUNET_CRYPTO_rsa_public_key_hash (rsa, + &h_rsa->hash); + +} + + void TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, struct TALER_DenominationHash *denom_hash) diff --git a/src/util/secmod_signatures.c b/src/util/secmod_signatures.c index f49cc20a5..077ce229a 100644 --- a/src/util/secmod_signatures.c +++ b/src/util/secmod_signatures.c @@ -70,8 +70,8 @@ TALER_exchange_secmod_eddsa_verify ( void -TALER_exchange_secmod_denom_sign ( - const struct TALER_DenominationHash *h_denom_pub, +TALER_exchange_secmod_rsa_sign ( + const struct TALER_RsaPubHashP *h_rsa, const char *section_name, struct GNUNET_TIME_Absolute start_sign, struct GNUNET_TIME_Relative duration, @@ -79,9 +79,9 @@ TALER_exchange_secmod_denom_sign ( struct TALER_SecurityModuleSignatureP *secm_sig) { struct TALER_DenominationKeyAnnouncementPS dka = { - .purpose.purpose = htonl (TALER_SIGNATURE_SM_DENOMINATION_KEY), + .purpose.purpose = htonl (TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY), .purpose.size = htonl (sizeof (dka)), - .h_denom_pub = *h_denom_pub, + .h_rsa = *h_rsa, .anchor_time = GNUNET_TIME_absolute_hton (start_sign), .duration_withdraw = GNUNET_TIME_relative_hton (duration) }; @@ -97,8 +97,8 @@ TALER_exchange_secmod_denom_sign ( enum GNUNET_GenericReturnValue -TALER_exchange_secmod_denom_verify ( - const struct TALER_DenominationHash *h_denom_pub, +TALER_exchange_secmod_rsa_verify ( + const struct TALER_RsaPubHashP *h_rsa, const char *section_name, struct GNUNET_TIME_Absolute start_sign, struct GNUNET_TIME_Relative duration, @@ -106,9 +106,9 @@ TALER_exchange_secmod_denom_verify ( const struct TALER_SecurityModuleSignatureP *secm_sig) { struct TALER_DenominationKeyAnnouncementPS dka = { - .purpose.purpose = htonl (TALER_SIGNATURE_SM_DENOMINATION_KEY), + .purpose.purpose = htonl (TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY), .purpose.size = htonl (sizeof (dka)), - .h_denom_pub = *h_denom_pub, + .h_rsa = *h_rsa, .anchor_time = GNUNET_TIME_absolute_hton (start_sign), .duration_withdraw = GNUNET_TIME_relative_hton (duration) }; @@ -117,7 +117,7 @@ TALER_exchange_secmod_denom_verify ( strlen (section_name) + 1, &dka.h_section_name); return - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_SM_DENOMINATION_KEY, + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY, &dka, &secm_sig->eddsa_signature, &secm_pub->eddsa_pub); diff --git a/src/util/taler-exchange-secmod-rsa.c b/src/util/taler-exchange-secmod-rsa.c index 7133a661b..49121c70e 100644 --- a/src/util/taler-exchange-secmod-rsa.c +++ b/src/util/taler-exchange-secmod-rsa.c @@ -88,7 +88,7 @@ struct DenominationKey /** * Hash of this denomination's public key. */ - struct TALER_DenominationHash h_denom_pub; + struct TALER_RsaPubHashP h_rsa; /** * Time at which this key is supposed to become valid. @@ -258,12 +258,12 @@ notify_client_dk_add (struct TES_Client *client, an->section_name_len = htons ((uint16_t) nlen); an->anchor_time = GNUNET_TIME_absolute_hton (dk->anchor); an->duration_withdraw = GNUNET_TIME_relative_hton (denom->duration_withdraw); - TALER_exchange_secmod_denom_sign (&dk->h_denom_pub, - denom->section, - dk->anchor, - denom->duration_withdraw, - &TES_smpriv, - &an->secm_sig); + TALER_exchange_secmod_rsa_sign (&dk->h_rsa, + denom->section, + dk->anchor, + denom->duration_withdraw, + &TES_smpriv, + &an->secm_sig); an->secm_pub = TES_smpub; p = (void *) &an[1]; memcpy (p, @@ -275,7 +275,7 @@ notify_client_dk_add (struct TES_Client *client, nlen); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending RSA denomination key %s (%s)\n", - GNUNET_h2s (&dk->h_denom_pub.hash), + GNUNET_h2s (&dk->h_rsa.hash), denom->section); if (GNUNET_OK != TES_transmit (client->csock, @@ -306,12 +306,12 @@ notify_client_dk_del (struct TES_Client *client, struct TALER_CRYPTO_RsaKeyPurgeNotification pn = { .header.type = htons (TALER_HELPER_RSA_MT_PURGE), .header.size = htons (sizeof (pn)), - .h_denom_pub = dk->h_denom_pub + .h_rsa = dk->h_rsa }; GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Sending RSA denomination expiration %s\n", - GNUNET_h2s (&dk->h_denom_pub.hash)); + GNUNET_h2s (&dk->h_rsa.hash)); if (GNUNET_OK != TES_transmit (client->csock, &pn.header)) @@ -345,7 +345,7 @@ handle_sign_request (struct TES_Client *client, GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); dk = GNUNET_CONTAINER_multihashmap_get (keys, - &sr->h_denom_pub.hash); + &sr->h_rsa.hash); if (NULL == dk) { struct TALER_CRYPTO_SignFailure sf = { @@ -357,7 +357,7 @@ handle_sign_request (struct TES_Client *client, GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Signing request failed, denomination key %s unknown\n", - GNUNET_h2s (&sr->h_denom_pub.hash)); + GNUNET_h2s (&sr->h_rsa.hash)); return TES_transmit (client->csock, &sf.header); } @@ -374,7 +374,7 @@ handle_sign_request (struct TES_Client *client, GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Signing request failed, denomination key %s is not yet valid\n", - GNUNET_h2s (&sr->h_denom_pub.hash)); + GNUNET_h2s (&sr->h_rsa.hash)); return TES_transmit (client->csock, &sf.header); } @@ -382,7 +382,7 @@ handle_sign_request (struct TES_Client *client, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received request to sign over %u bytes with key %s\n", (unsigned int) blinded_msg_size, - GNUNET_h2s (&sr->h_denom_pub.hash)); + GNUNET_h2s (&sr->h_rsa.hash)); GNUNET_assert (dk->rc < UINT_MAX); dk->rc++; GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); @@ -470,8 +470,8 @@ setup_key (struct DenominationKey *dk, } buf_size = GNUNET_CRYPTO_rsa_private_key_encode (priv, &buf); - GNUNET_CRYPTO_rsa_public_key_hash (pub, - &dk->h_denom_pub.hash); + TALER_rsa_pub_hash (pub, + &dk->h_rsa); GNUNET_asprintf (&dk->filename, "%s/%s/%llu", keydir, @@ -495,7 +495,7 @@ setup_key (struct DenominationKey *dk, GNUNET_free (buf); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Setup fresh private key %s at %s in `%s' (generation #%llu)\n", - GNUNET_h2s (&dk->h_denom_pub.hash), + GNUNET_h2s (&dk->h_rsa.hash), GNUNET_STRINGS_absolute_time_to_string (dk->anchor), dk->filename, (unsigned long long) key_gen); @@ -505,7 +505,7 @@ setup_key (struct DenominationKey *dk, if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put ( keys, - &dk->h_denom_pub.hash, + &dk->h_rsa.hash, dk, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { @@ -563,13 +563,13 @@ handle_revoke_request (struct TES_Client *client, GNUNET_assert (0 == pthread_mutex_lock (&keys_lock)); dk = GNUNET_CONTAINER_multihashmap_get (keys, - &rr->h_denom_pub.hash); + &rr->h_rsa.hash); if (NULL == dk) { GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock)); GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Revocation request ignored, denomination key %s unknown\n", - GNUNET_h2s (&rr->h_denom_pub.hash)); + GNUNET_h2s (&rr->h_rsa.hash)); return GNUNET_OK; } @@ -877,7 +877,7 @@ update_keys (struct Denomination *denom, GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove ( keys, - &key->h_denom_pub.hash, + &key->h_rsa.hash, key)); if ( (! key->purge) && (0 != unlink (key->filename)) ) @@ -1029,19 +1029,19 @@ parse_key (struct Denomination *denom, dk->denom = denom; dk->anchor = anchor; dk->filename = GNUNET_strdup (filename); - GNUNET_CRYPTO_rsa_public_key_hash (pub, - &dk->h_denom_pub.hash); + TALER_rsa_pub_hash (pub, + &dk->h_rsa); dk->denom_pub = pub; if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put ( keys, - &dk->h_denom_pub.hash, + &dk->h_rsa.hash, dk, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Duplicate private key %s detected in file `%s'. Skipping.\n", - GNUNET_h2s (&dk->h_denom_pub.hash), + GNUNET_h2s (&dk->h_rsa.hash), filename); GNUNET_CRYPTO_rsa_private_key_free (priv); GNUNET_CRYPTO_rsa_public_key_free (pub); @@ -1063,7 +1063,7 @@ parse_key (struct Denomination *denom, dk); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Imported key %s from `%s'\n", - GNUNET_h2s (&dk->h_denom_pub.hash), + GNUNET_h2s (&dk->h_rsa.hash), filename); } } diff --git a/src/util/taler-exchange-secmod-rsa.h b/src/util/taler-exchange-secmod-rsa.h index 1723560a5..b0fdfbd96 100644 --- a/src/util/taler-exchange-secmod-rsa.h +++ b/src/util/taler-exchange-secmod-rsa.h @@ -35,6 +35,7 @@ GNUNET_NETWORK_STRUCT_BEGIN + /** * Message sent if a key is available. */ @@ -76,7 +77,7 @@ struct TALER_CRYPTO_RsaKeyAvailableNotification */ struct TALER_SecurityModuleSignatureP secm_sig; - /* followed by @e pub_size bytes of the public key */ + /* followed by @e pub_size bytes of the RSA public key */ /* followed by @e section_name bytes of the configuration section name of the denomination of this key */ @@ -102,8 +103,7 @@ struct TALER_CRYPTO_RsaKeyPurgeNotification /** * Hash of the public key of the purged RSA key. */ - // FIXME: wrong type, not hashed with age restriction here! - struct TALER_DenominationHash h_denom_pub; + struct TALER_RsaPubHashP h_rsa; }; @@ -126,8 +126,7 @@ struct TALER_CRYPTO_SignRequest /** * Hash of the public key of the RSA key to use for the signature. */ - // FIXME: wrong type, not hashed with age restriction here! - struct TALER_DenominationHash h_denom_pub; + struct TALER_RsaPubHashP h_rsa; /* followed by message to sign */ }; @@ -151,8 +150,7 @@ struct TALER_CRYPTO_RevokeRequest /** * Hash of the public key of the revoked RSA key. */ - // FIXME: wrong type, not hashed with age restriction here! - struct TALER_DenominationHash h_denom_pub; + struct TALER_RsaPubHashP h_rsa; }; -- cgit v1.2.3