merchant

Merchant backend to process payments, run by merchants
Log | Files | Refs | Submodules | README | LICENSE

taler-merchant-httpd_token-keys.h (7440B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2026 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file src/backend/taler-merchant-httpd_token-keys.h
     18  * @brief shared token family key lookup, lifetime extension and creation
     19  *        for orders and fountains; also provides fountain key windows
     20  * @author Christian Blättler
     21  * @author Bohdan Potuzhnyi
     22  */
     23 #ifndef TALER_MERCHANT_HTTPD_TOKEN_KEYS_H
     24 #define TALER_MERCHANT_HTTPD_TOKEN_KEYS_H
     25 
     26 #include "taler-merchant-httpd.h"
     27 #include "taler/taler_merchant_util.h"
     28 #include "merchantdb_lib.h"
     29 #include "merchant-database/get_token_family_key.h"
     30 
     31 /**
     32  * Hard cap on the ``key_window_size`` of a fountain grant.  Every
     33  * advertised future slot may require minting (and storing) a fresh
     34  * blind-signing key pair on ``GET /fountain/info``, so an unbounded
     35  * window would be a denial-of-service vector.
     36  */
     37 #define TMH_MAX_FOUNTAIN_KEY_WINDOW 12
     38 
     39 /**
     40  * Hard cap on the total number of token envelopes in one
     41  * ``POST /fountain/withdraw`` request.  Matches the cap on token
     42  * outputs of the pay endpoint.
     43  */
     44 #define TMH_MAX_FOUNTAIN_ENVELOPES 64
     45 
     46 
     47 /**
     48  * Extend the lifetime of existing private keys covering @a valid_at
     49  * until at least @a sign_until. Does not create a key. Order creation
     50  * also calls this when reusing a key already added to the contract.
     51  *
     52  * @param connection connection to report errors on
     53  * @param instance_id instance owning the token family
     54  * @param slug slug of the token family
     55  * @param valid_at time at which the tokens must be valid
     56  * @param sign_until how long the private key must remain usable
     57  * @return #GNUNET_OK on success, #GNUNET_NO if an error response was
     58  *         queued, #GNUNET_SYSERR on hard failure
     59  */
     60 enum GNUNET_GenericReturnValue
     61 TMH_token_key_extend (
     62   struct MHD_Connection *connection,
     63   const char *instance_id,
     64   const char *slug,
     65   struct GNUNET_TIME_Timestamp valid_at,
     66   struct GNUNET_TIME_Timestamp sign_until);
     67 
     68 
     69 /**
     70  * Ensure that an issue key of token family @a slug covering @a valid_at
     71  * exists and that its private key remains usable for signing until at
     72  * least @a sign_until.  If a key covering @a valid_at exists but its
     73  * private key would be deleted earlier, the private key's lifetime is
     74  * extended; only if no key covers @a valid_at at all is a new key pair
     75  * generated and stored in the database.
     76  *
     77  * @param connection connection to report errors on
     78  * @param instance_id instance owning the token family
     79  * @param slug slug of the token family
     80  * @param valid_at time at which tokens signed with the key must be valid;
     81  *        determines the key's validity period
     82  * @param sign_until how long the private key must remain usable
     83  * @param[out] key_details set to the key (public and private part), its
     84  *        validity bounds and the token family details; on success the
     85  *        caller must release it via #TMH_token_key_details_free()
     86  * @param[out] minted set to true if a fresh key pair was created
     87  * @return #GNUNET_OK on success (and only then is @a key_details set),
     88  *         #GNUNET_NO if an error response was already queued on
     89  *         @a connection, #GNUNET_SYSERR on hard failure
     90  */
     91 enum GNUNET_GenericReturnValue
     92 TMH_token_key_ensure (
     93   struct MHD_Connection *connection,
     94   const char *instance_id,
     95   const char *slug,
     96   struct GNUNET_TIME_Timestamp valid_at,
     97   struct GNUNET_TIME_Timestamp sign_until,
     98   struct TALER_MERCHANTDB_TokenFamilyKeyDetails *key_details,
     99   bool *minted);
    100 
    101 
    102 /**
    103  * Release all resources of @a key_details (but not the structure
    104  * itself, which is typically stack-allocated).
    105  *
    106  * @param[in,out] key_details result of a successful
    107  *        #TMH_token_key_ensure() to release
    108  */
    109 void
    110 TMH_token_key_details_free (
    111   struct TALER_MERCHANTDB_TokenFamilyKeyDetails *key_details);
    112 
    113 
    114 /**
    115  * Current and future keys of a fountain grant, in order of strictly
    116  * increasing expiry. Owns the key and family details.
    117  */
    118 struct TMH_TokenKeyWindow
    119 {
    120   /** Keys selected using the shared order lookup and generation logic. */
    121   struct TALER_MERCHANTDB_TokenFamilyKeyDetails *keys;
    122 
    123   /** Number of keys; at most key_window_size + 1. */
    124   unsigned int keys_len;
    125 };
    126 
    127 
    128 /**
    129  * Obtain the current key and up to @a key_window_size future keys.
    130  * The first lookup is at max(now, family.valid_after); each subsequent
    131  * lookup is one second beyond the previous key's actual expiry, capped
    132  * at now + key_window_size * duration. No key may start after that
    133  * horizon, including when the family itself starts in the future.
    134  * Rounding can make the validity intervals overlap. Stop at the family
    135  * expiry or when the existing validity rules cannot extend coverage.
    136  *
    137  * @param connection connection to report errors on
    138  * @param instance_id instance owning the token family
    139  * @param tf token family details
    140  * @param now time of this request, also the private-key retention minimum
    141  * @param key_window_size number of future keys, at most
    142  *        #TMH_MAX_FOUNTAIN_KEY_WINDOW (zero allows the current key only)
    143  * @param[out] window initialized window; empty on error
    144  * @return #GNUNET_OK on success (possibly an empty/shorter window),
    145  *         #GNUNET_NO if an error response was queued,
    146  *         #GNUNET_SYSERR on hard failure
    147  */
    148 enum GNUNET_GenericReturnValue
    149 TMH_token_key_window_get (
    150   struct MHD_Connection *connection,
    151   const char *instance_id,
    152   const struct TALER_MERCHANTDB_TokenFamilyDetails *tf,
    153   struct GNUNET_TIME_Timestamp now,
    154   unsigned int key_window_size,
    155   struct TMH_TokenKeyWindow *window);
    156 
    157 
    158 /**
    159  * Release the window's keys and family details and reset it to empty.
    160  *
    161  * @param[in,out] window window to release
    162  */
    163 void
    164 TMH_token_key_window_free (struct TMH_TokenKeyWindow *window);
    165 
    166 
    167 /**
    168  * Select a key from an advertised window. An exact validity-start match
    169  * takes precedence over overlapping earlier keys. Otherwise the first
    170  * key covering @a valid_at is selected. A missing valid_at in the wallet
    171  * request selects index zero directly, rather than calling this function.
    172  *
    173  * @param window current window of the grant
    174  * @param valid_at requested validity time
    175  * @param[out] key_index selected index
    176  * @return #GNUNET_OK on match, #GNUNET_NO if outside the window
    177  */
    178 enum GNUNET_GenericReturnValue
    179 TMH_token_key_window_find (
    180   const struct TMH_TokenKeyWindow *window,
    181   struct GNUNET_TIME_Timestamp valid_at,
    182   unsigned int *key_index);
    183 
    184 
    185 /**
    186  * Convert token family details from the database into a contract
    187  * token family (without keys).  The result must be released via
    188  * #TALER_MERCHANT_contract_token_family_free().
    189  *
    190  * @param tf token family details from the database
    191  * @param[out] family initialized contract token family
    192  */
    193 void
    194 TMH_token_family_to_contract (
    195   const struct TALER_MERCHANTDB_TokenFamilyDetails *tf,
    196   struct TALER_MERCHANT_ContractTokenFamily *family);
    197 
    198 #endif