418 lines
14 KiB
C
418 lines
14 KiB
C
/*
|
|
This file is part of TALER
|
|
Copyright (C) 2020 Taler Systems SA
|
|
|
|
TALER is free software; you can redistribute it and/or modify it under the
|
|
terms of the GNU Affero 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 Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License along with
|
|
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
*/
|
|
/**
|
|
* @file taler-exchange-httpd_keys.h
|
|
* @brief management of our various keys
|
|
* @author Christian Grothoff
|
|
*/
|
|
#include "platform.h"
|
|
#include "taler_json_lib.h"
|
|
#include "taler_mhd_lib.h"
|
|
#include "taler-exchange-httpd_responses.h"
|
|
|
|
|
|
#ifndef TALER_EXCHANGE_HTTPD_KEYS_H
|
|
#define TALER_EXCHANGE_HTTPD_KEYS_H
|
|
|
|
/**
|
|
* Signatures of an auditor over a denomination key of this exchange.
|
|
*/
|
|
struct TEH_AuditorSignature;
|
|
|
|
|
|
/**
|
|
* @brief All information about a denomination key (which is used to
|
|
* sign coins into existence).
|
|
*/
|
|
struct TEH_DenominationKey
|
|
{
|
|
|
|
/**
|
|
* Decoded denomination public key (the hash of it is in
|
|
* @e issue, but we sometimes need the full public key as well).
|
|
*/
|
|
struct TALER_DenominationPublicKey denom_pub;
|
|
|
|
/**
|
|
* Hash code of the denomination public key.
|
|
*/
|
|
struct TALER_DenominationHash h_denom_pub;
|
|
|
|
/**
|
|
* Meta data about the type of the denomination, such as fees and validity
|
|
* periods.
|
|
*/
|
|
struct TALER_EXCHANGEDB_DenominationKeyMetaData meta;
|
|
|
|
/**
|
|
* The long-term offline master key's signature for this denomination.
|
|
* Signs over @e h_denom_pub and @e meta.
|
|
*/
|
|
struct TALER_MasterSignatureP master_sig;
|
|
|
|
/**
|
|
* We store the auditor signatures for this denomination in a DLL.
|
|
*/
|
|
struct TEH_AuditorSignature *as_head;
|
|
|
|
/**
|
|
* We store the auditor signatures for this denomination in a DLL.
|
|
*/
|
|
struct TEH_AuditorSignature *as_tail;
|
|
|
|
/**
|
|
* Set to 'true' if this denomination has been revoked and recoup is
|
|
* thus supported right now.
|
|
*/
|
|
bool recoup_possible;
|
|
|
|
};
|
|
|
|
|
|
/**
|
|
* Snapshot of the (coin and signing) keys (including private keys) of
|
|
* the exchange. There can be multiple instances of this struct, as it is
|
|
* reference counted and only destroyed once the last user is done
|
|
* with it. The current instance is acquired using
|
|
* #TEH_KS_acquire(). Using this function increases the
|
|
* reference count. The contents of this structure (except for the
|
|
* reference counter) should be considered READ-ONLY until it is
|
|
* ultimately destroyed (as there can be many concurrent users).
|
|
*/
|
|
struct TEH_KeyStateHandle;
|
|
|
|
|
|
/**
|
|
* Run internal invariant checks. For debugging.
|
|
*/
|
|
void
|
|
TEH_check_invariants (void);
|
|
|
|
|
|
/**
|
|
* Return the current key state for this thread. Possibly re-builds the key
|
|
* state if we have reason to believe that something changed.
|
|
*
|
|
* The result is ONLY valid until the next call to
|
|
* #TEH_keys_denomination_by_hash() or #TEH_keys_get_state()
|
|
* or #TEH_keys_exchange_sign().
|
|
*
|
|
* @return NULL on error
|
|
*/
|
|
struct TEH_KeyStateHandle *
|
|
TEH_keys_get_state (void);
|
|
|
|
|
|
/**
|
|
* Something changed in the database. Rebuild all key states. This function
|
|
* should be called if the exchange learns about a new signature from an
|
|
* auditor or our master key.
|
|
*
|
|
* (We do not do so immediately, but merely signal to all threads that they
|
|
* need to rebuild their key state upon the next call to
|
|
* #TEH_keys_get_state()).
|
|
*/
|
|
void
|
|
TEH_keys_update_states (void);
|
|
|
|
|
|
/**
|
|
* Look up the issue for a denom public key. Note that the result
|
|
* must only be used in this thread and only until another key or
|
|
* key state is resolved.
|
|
*
|
|
* @param h_denom_pub hash of denomination public key
|
|
* @param[in,out] conn used to return status message if NULL is returned
|
|
* @param[out] mret set to the MHD status if NULL is returned
|
|
* @return the denomination key issue,
|
|
* or NULL if @a h_denom_pub could not be found
|
|
*/
|
|
struct TEH_DenominationKey *
|
|
TEH_keys_denomination_by_hash (const struct TALER_DenominationHash *h_denom_pub,
|
|
struct MHD_Connection *conn,
|
|
MHD_RESULT *mret);
|
|
|
|
|
|
/**
|
|
* Look up the issue for a denom public key using a given @a ksh. This allows
|
|
* requesting multiple denominations with the same @a ksh which thus will
|
|
* remain valid until the next call to #TEH_keys_denomination_by_hash() or
|
|
* #TEH_keys_get_state() or #TEH_keys_exchange_sign().
|
|
*
|
|
* @param ksh key state state to look in
|
|
* @param h_denom_pub hash of denomination public key
|
|
* @param[in,out] conn connection used to return status message if NULL is returned
|
|
* @param[out] mret set to the MHD status if NULL is returned
|
|
* @return the denomination key issue,
|
|
* or NULL if @a h_denom_pub could not be found
|
|
*/
|
|
struct TEH_DenominationKey *
|
|
TEH_keys_denomination_by_hash2 (struct TEH_KeyStateHandle *ksh,
|
|
const struct
|
|
TALER_DenominationHash *h_denom_pub,
|
|
struct MHD_Connection *conn,
|
|
MHD_RESULT *mret);
|
|
|
|
/**
|
|
* Request to sign @a msg using the public key corresponding to
|
|
* @a h_denom_pub.
|
|
*
|
|
* @param h_denom_pub hash of the public key to use to sign
|
|
* @param bp blinded planchet to sign
|
|
* @param[out] ec set to the error code (or #TALER_EC_NONE on success)
|
|
* @return signature, the value inside the structure will be NULL on failure,
|
|
* see @a ec for details about the failure
|
|
*/
|
|
struct TALER_BlindedDenominationSignature
|
|
TEH_keys_denomination_sign (const struct TALER_DenominationHash *h_denom_pub,
|
|
const struct TALER_BlindedPlanchet *bp,
|
|
enum TALER_ErrorCode *ec);
|
|
|
|
|
|
/**
|
|
* Request to derive CS r_pub using the denomination corresponding to @a h_denom_pub
|
|
* and @a nonce.
|
|
*
|
|
* @param h_denom_pub hash of the public key to use to derive r_pub
|
|
* @param nonce withdraw/refresh nonce
|
|
* @param[out] ec set to the error code (or #TALER_EC_NONE on success)
|
|
* @return r_pub, the value inside the structure will be NULL on failure,
|
|
* see @a ec for details about the failure
|
|
*/
|
|
enum TALER_ErrorCode
|
|
TEH_keys_denomination_cs_r_pub (const struct
|
|
TALER_DenominationHash *h_denom_pub,
|
|
const struct TALER_CsNonce *nonce,
|
|
struct TALER_DenominationCSPublicRPairP *r_pub);
|
|
|
|
|
|
/**
|
|
* Revoke the public key associated with @param h_denom_pub .
|
|
* This function should be called AFTER the database was
|
|
* updated, as it also triggers #TEH_keys_update_states().
|
|
*
|
|
* Note that the actual revocation happens asynchronously and
|
|
* may thus fail silently. To verify that the revocation succeeded,
|
|
* clients must watch for the associated change to the key state.
|
|
*
|
|
* @param h_denom_pub hash of the public key to revoke
|
|
*/
|
|
void
|
|
TEH_keys_denomination_revoke (const struct TALER_DenominationHash *h_denom_pub);
|
|
|
|
|
|
/**
|
|
* Fully clean up keys subsystem.
|
|
*/
|
|
void
|
|
TEH_keys_finished (void);
|
|
|
|
|
|
/**
|
|
* Resumse all suspended /keys requests, we may now have key material
|
|
* (or are shutting down).
|
|
*
|
|
* @param do_shutdown are we shutting down?
|
|
*/
|
|
void
|
|
TEH_resume_keys_requests (bool do_shutdown);
|
|
|
|
|
|
/**
|
|
* Sign the message in @a purpose with the exchange's signing key.
|
|
*
|
|
* The @a purpose data is the beginning of the data of which the signature is
|
|
* to be created. The `size` field in @a purpose must correctly indicate the
|
|
* number of bytes of the data structure, including its header. Use
|
|
* #TEH_keys_exchange_sign() instead of calling this function directly!
|
|
*
|
|
* @param purpose the message to sign
|
|
* @param[out] pub set to the current public signing key of the exchange
|
|
* @param[out] sig signature over purpose using current signing key
|
|
* @return #TALER_EC_NONE on success
|
|
*/
|
|
enum TALER_ErrorCode
|
|
TEH_keys_exchange_sign_ (
|
|
const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
|
|
struct TALER_ExchangePublicKeyP *pub,
|
|
struct TALER_ExchangeSignatureP *sig);
|
|
|
|
|
|
/**
|
|
* Sign the message in @a purpose with the exchange's signing key.
|
|
*
|
|
* The @a purpose data is the beginning of the data of which the signature is
|
|
* to be created. The `size` field in @a purpose must correctly indicate the
|
|
* number of bytes of the data structure, including its header. Use
|
|
* #TEH_keys_exchange_sign() instead of calling this function directly!
|
|
*
|
|
* @param ksh key state state to look in
|
|
* @param purpose the message to sign
|
|
* @param[out] pub set to the current public signing key of the exchange
|
|
* @param[out] sig signature over purpose using current signing key
|
|
* @return #TALER_EC_NONE on success
|
|
*/
|
|
enum TALER_ErrorCode
|
|
TEH_keys_exchange_sign2_ (
|
|
struct TEH_KeyStateHandle *ksh,
|
|
const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
|
|
struct TALER_ExchangePublicKeyP *pub,
|
|
struct TALER_ExchangeSignatureP *sig);
|
|
|
|
|
|
/**
|
|
* @ingroup crypto
|
|
* @brief EdDSA sign a given block.
|
|
*
|
|
* The @a ps data must be a fixed-size struct for which the signature is to be
|
|
* created. The `size` field in @a ps->purpose must correctly indicate the
|
|
* number of bytes of the data structure, including its header.
|
|
*
|
|
* @param ps packed struct with what to sign, MUST begin with a purpose
|
|
* @param[out] pub where to store the public key to use for the signing
|
|
* @param[out] sig where to write the signature
|
|
* @return #TALER_EC_NONE on success
|
|
*/
|
|
#define TEH_keys_exchange_sign(ps,pub,sig) \
|
|
({ \
|
|
/* check size is set correctly */ \
|
|
GNUNET_assert (htonl ((ps)->purpose.size) == \
|
|
sizeof (*ps)); \
|
|
/* check 'ps' begins with the purpose */ \
|
|
GNUNET_static_assert (((void*) (ps)) == \
|
|
((void*) &(ps)->purpose)); \
|
|
TEH_keys_exchange_sign_ (&(ps)->purpose, \
|
|
pub, \
|
|
sig); \
|
|
})
|
|
|
|
|
|
/**
|
|
* @ingroup crypto
|
|
* @brief EdDSA sign a given block.
|
|
*
|
|
* The @a ps data must be a fixed-size struct for which the signature is to be
|
|
* created. The `size` field in @a ps->purpose must correctly indicate the
|
|
* number of bytes of the data structure, including its header.
|
|
*
|
|
* This allows requesting multiple denominations with the same @a ksh which
|
|
* thus will remain valid until the next call to
|
|
* #TEH_keys_denomination_by_hash() or #TEH_keys_get_state() or
|
|
* #TEH_keys_exchange_sign().
|
|
*
|
|
* @param ksh key state to use
|
|
* @param ps packed struct with what to sign, MUST begin with a purpose
|
|
* @param[out] pub where to store the public key to use for the signing
|
|
* @param[out] sig where to write the signature
|
|
* @return #TALER_EC_NONE on success
|
|
*/
|
|
#define TEH_keys_exchange_sign2(ksh,ps,pub,sig) \
|
|
({ \
|
|
/* check size is set correctly */ \
|
|
GNUNET_assert (htonl ((ps)->purpose.size) == \
|
|
sizeof (*ps)); \
|
|
/* check 'ps' begins with the purpose */ \
|
|
GNUNET_static_assert (((void*) (ps)) == \
|
|
((void*) &(ps)->purpose)); \
|
|
TEH_keys_exchange_sign2_ (ksh, \
|
|
&(ps)->purpose, \
|
|
pub, \
|
|
sig); \
|
|
})
|
|
|
|
|
|
/**
|
|
* Revoke the given exchange's signing key.
|
|
* This function should be called AFTER the database was
|
|
* updated, as it also triggers #TEH_keys_update_states().
|
|
*
|
|
* Note that the actual revocation happens asynchronously and
|
|
* may thus fail silently. To verify that the revocation succeeded,
|
|
* clients must watch for the associated change to the key state.
|
|
*
|
|
* @param exchange_pub key to revoke
|
|
*/
|
|
void
|
|
TEH_keys_exchange_revoke (const struct TALER_ExchangePublicKeyP *exchange_pub);
|
|
|
|
|
|
/**
|
|
* Function to call to handle requests to "/keys" by sending
|
|
* back our current key material.
|
|
*
|
|
* @param rc request context
|
|
* @param args array of additional options (must be empty for this function)
|
|
* @return MHD result code
|
|
*/
|
|
MHD_RESULT
|
|
TEH_keys_get_handler (struct TEH_RequestContext *rc,
|
|
const char *const args[]);
|
|
|
|
|
|
/**
|
|
* Function to call to handle requests to "/management/keys" by sending
|
|
* back our future key material.
|
|
*
|
|
* @param rh context of the handler
|
|
* @param connection the MHD connection to handle
|
|
* @return MHD result code
|
|
*/
|
|
MHD_RESULT
|
|
TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
|
|
struct MHD_Connection *connection);
|
|
|
|
|
|
/**
|
|
* Load fees and expiration times (!) for the denomination type configured for
|
|
* the denomination matching @a h_denom_pub.
|
|
*
|
|
* @param h_denom_pub hash of the denomination public key
|
|
* to use to derive the section name of the configuration to use
|
|
* @param[out] denom_pub set to the denomination public key (to be freed by caller!)
|
|
* @param[out] meta denomination type data to complete
|
|
* @return #GNUNET_OK on success,
|
|
* #GNUNET_NO if @a h_denom_pub is not known
|
|
* #GNUNET_SYSERR on hard errors
|
|
*/
|
|
enum GNUNET_GenericReturnValue
|
|
TEH_keys_load_fees (const struct TALER_DenominationHash *h_denom_pub,
|
|
struct TALER_DenominationPublicKey *denom_pub,
|
|
struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta);
|
|
|
|
|
|
/**
|
|
* Load expiration times for the given onling signing key.
|
|
*
|
|
* @param exchange_pub the online signing key
|
|
* @param[out] meta set to meta data about the key
|
|
* @return #GNUNET_OK on success
|
|
*/
|
|
enum GNUNET_GenericReturnValue
|
|
TEH_keys_get_timing (const struct TALER_ExchangePublicKeyP *exchange_pub,
|
|
struct TALER_EXCHANGEDB_SignkeyMetaData *meta);
|
|
|
|
|
|
/**
|
|
* Initialize keys subsystem.
|
|
*
|
|
* @return #GNUNET_OK on success
|
|
*/
|
|
enum GNUNET_GenericReturnValue
|
|
TEH_keys_init (void);
|
|
|
|
|
|
#endif
|