exchange

Base system with REST service to issue digital coins, run by the payment service provider
Log | Files | Refs | Submodules | README | LICENSE

taler-exchange-httpd_secmod-helpers.c (28527B)


      1 /*
      2    This file is part of TALER
      3    Copyright (C) 2020-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 taler-exchange-httpd_secmod-helpers.c
     18  * @brief management of state with secmod helpers
     19  * @author Christian Grothoff
     20  * @author Özgür Kesim
     21  */
     22 #include "taler/taler_json_lib.h"
     23 #include "taler/taler_mhd_lib.h"
     24 #include "taler-exchange-httpd.h"
     25 #include "taler-exchange-httpd_get-keys.h"
     26 #include "taler-exchange-httpd_secmod-helpers.h"
     27 #include "taler-exchange-httpd_configuration.h"
     28 
     29 
     30 /**
     31  * For how long should a signing key be legally retained?
     32  * Configuration value.
     33  */
     34 static struct GNUNET_TIME_Relative signkey_legal_duration;
     35 
     36 /**
     37  * Handle for the esign/EdDSA helper.
     38  */
     39 static struct TALER_CRYPTO_ExchangeSignHelper *esh;
     40 
     41 /**
     42  * Handle for the denom/RSA helper.
     43  */
     44 static struct TALER_CRYPTO_RsaDenominationHelper *rsadh;
     45 
     46 /**
     47  * Handle for the denom/CS helper.
     48  */
     49 static struct TALER_CRYPTO_CsDenominationHelper *csdh;
     50 
     51 /**
     52  * Map from H(denom_pub) to `struct HelperDenomination` entries.
     53  */
     54 static struct GNUNET_CONTAINER_MultiHashMap *denom_keys;
     55 
     56 /**
     57  * Map from H(rsa_pub) to `struct HelperDenomination` entries.
     58  */
     59 static struct GNUNET_CONTAINER_MultiHashMap *rsa_keys;
     60 
     61 /**
     62  * Map from H(cs_pub) to `struct HelperDenomination` entries.
     63  */
     64 static struct GNUNET_CONTAINER_MultiHashMap *cs_keys;
     65 
     66 /**
     67  * Map from `struct TALER_ExchangePublicKey` to `struct HelperSignkey`
     68  * entries.  Based on the fact that a `struct GNUNET_PeerIdentity` is also
     69  * an EdDSA public key.
     70  */
     71 static struct GNUNET_CONTAINER_MultiPeerMap *esign_keys;
     72 
     73 /**
     74  * RSA security module public key, all zero if not known.
     75  */
     76 static struct TALER_SecurityModulePublicKeyP denom_rsa_sm_pub;
     77 
     78 /**
     79  * CS security module public key, all zero if not known.
     80  */
     81 static struct TALER_SecurityModulePublicKeyP denom_cs_sm_pub;
     82 
     83 /**
     84  * EdDSA security module public key, all zero if not known.
     85  */
     86 static struct TALER_SecurityModulePublicKeyP esign_sm_pub;
     87 
     88 
     89 bool
     90 TEH_SECMOD_have_denom_sm_pub ()
     91 {
     92   return
     93     (! GNUNET_is_zero (&denom_rsa_sm_pub)) ||
     94     (! GNUNET_is_zero (&denom_cs_sm_pub));
     95 }
     96 
     97 
     98 bool
     99 TEH_SECMOD_have_esign_sm_pub ()
    100 {
    101   return ! GNUNET_is_zero (&esign_sm_pub);
    102 }
    103 
    104 
    105 json_t *
    106 TEH_SECMOD_get_sm_pubs_as_json ()
    107 {
    108   return GNUNET_JSON_PACK (
    109     GNUNET_JSON_pack_data_auto ("denom_secmod_public_key",
    110                                 &denom_rsa_sm_pub),
    111     GNUNET_JSON_pack_data_auto ("denom_secmod_cs_public_key",
    112                                 &denom_cs_sm_pub),
    113     GNUNET_JSON_pack_data_auto ("signkey_secmod_public_key",
    114                                 &esign_sm_pub));
    115 }
    116 
    117 
    118 /**
    119  * Check that the given RSA security module's public key is the one
    120  * we have pinned.  If it does not match, we die hard.
    121  *
    122  * @param sm_pub RSA security module public key to check
    123  */
    124 static void
    125 check_denom_rsa_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub)
    126 {
    127   if (0 !=
    128       GNUNET_memcmp (sm_pub,
    129                      &denom_rsa_sm_pub))
    130   {
    131     if (! GNUNET_is_zero (&denom_rsa_sm_pub))
    132     {
    133       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    134                   "Our RSA security module changed its key. This must not happen.\n");
    135       GNUNET_assert (0);
    136     }
    137     denom_rsa_sm_pub = *sm_pub; /* TOFU ;-) */
    138   }
    139 }
    140 
    141 
    142 /**
    143  * Function called with information about available keys for signing.  Usually
    144  * only called once per key upon connect. Also called again in case a key is
    145  * being revoked, in that case with an @a end_time of zero.
    146  *
    147  * @param cls NULL
    148  * @param section_name name of the denomination type in the configuration;
    149  *                 NULL if the key has been revoked or purged
    150  * @param start_time when does the key become available for signing;
    151  *                 zero if the key has been revoked or purged
    152  * @param validity_duration how long does the key remain available for signing;
    153  *                 zero if the key has been revoked or purged
    154  * @param h_rsa hash of the @a denom_pub that is available (or was purged)
    155  * @param bs_pub the public key itself, NULL if the key was revoked or purged
    156  * @param sm_pub public key of the security module, NULL if the key was revoked or purged
    157  * @param sm_sig signature from the security module
    158  */
    159 static void
    160 helper_rsa_cb (
    161   void *cls,
    162   const char *section_name,
    163   struct GNUNET_TIME_Timestamp start_time,
    164   struct GNUNET_TIME_Relative validity_duration,
    165   const struct TALER_RsaPubHashP *h_rsa,
    166   struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
    167   const struct TALER_SecurityModulePublicKeyP *sm_pub,
    168   const struct TALER_SecurityModuleSignatureP *sm_sig)
    169 {
    170   struct HelperDenomination *hd;
    171 
    172   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    173               "RSA helper announces key %s for denomination type %s with validity %s\n",
    174               GNUNET_h2s (&h_rsa->hash),
    175               section_name,
    176               GNUNET_STRINGS_relative_time_to_string (validity_duration,
    177                                                       GNUNET_NO));
    178   TEH_keys_bump_generation ();
    179   TEH_resume_keys_requests (false);
    180   hd = GNUNET_CONTAINER_multihashmap_get (rsa_keys,
    181                                           &h_rsa->hash);
    182   if (NULL != hd)
    183   {
    184     /* should be just an update (revocation!), so update existing entry */
    185     hd->validity_duration = validity_duration;
    186     return;
    187   }
    188   GNUNET_assert (NULL != sm_pub);
    189   check_denom_rsa_sm_pub (sm_pub);
    190   hd = GNUNET_new (struct HelperDenomination);
    191   hd->start_time = start_time;
    192   hd->validity_duration = validity_duration;
    193   hd->h_details.h_rsa = *h_rsa;
    194   hd->sm_sig = *sm_sig;
    195   GNUNET_assert (GNUNET_CRYPTO_BSA_RSA == bs_pub->cipher);
    196   hd->denom_pub.bsign_pub_key =
    197     GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
    198   /* load the age mask for the denomination, if applicable */
    199   hd->denom_pub.age_mask = TEH_CONFIG_load_age_mask (section_name);
    200   TALER_denom_pub_hash (&hd->denom_pub,
    201                         &hd->h_denom_pub);
    202   hd->section_name = GNUNET_strdup (section_name);
    203   GNUNET_assert (
    204     GNUNET_OK ==
    205     GNUNET_CONTAINER_multihashmap_put (
    206       denom_keys,
    207       &hd->h_denom_pub.hash,
    208       hd,
    209       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    210   GNUNET_assert (
    211     GNUNET_OK ==
    212     GNUNET_CONTAINER_multihashmap_put (
    213       rsa_keys,
    214       &hd->h_details.h_rsa.hash,
    215       hd,
    216       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    217 }
    218 
    219 
    220 /**
    221  * Check that the given CS security module's public key is the one
    222  * we have pinned.  If it does not match, we die hard.
    223  *
    224  * @param sm_pub RSA security module public key to check
    225  */
    226 static void
    227 check_denom_cs_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub)
    228 {
    229   if (0 !=
    230       GNUNET_memcmp (sm_pub,
    231                      &denom_cs_sm_pub))
    232   {
    233     if (! GNUNET_is_zero (&denom_cs_sm_pub))
    234     {
    235       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    236                   "Our CS security module changed its key. This must not happen.\n");
    237       GNUNET_assert (0);
    238     }
    239     denom_cs_sm_pub = *sm_pub; /* TOFU ;-) */
    240   }
    241 }
    242 
    243 
    244 /**
    245  * Function called with information about available CS keys for signing. Usually
    246  * only called once per key upon connect. Also called again in case a key is
    247  * being revoked, in that case with an @a end_time of zero.
    248  *
    249  * @param cls NULL
    250  * @param section_name name of the denomination type in the configuration;
    251  *                 NULL if the key has been revoked or purged
    252  * @param start_time when does the key become available for signing;
    253  *                 zero if the key has been revoked or purged
    254  * @param validity_duration how long does the key remain available for signing;
    255  *                 zero if the key has been revoked or purged
    256  * @param h_cs hash of the @a denom_pub that is available (or was purged)
    257  * @param bs_pub the public key itself, NULL if the key was revoked or purged
    258  * @param sm_pub public key of the security module, NULL if the key was revoked or purged
    259  * @param sm_sig signature from the security module
    260  */
    261 static void
    262 helper_cs_cb (
    263   void *cls,
    264   const char *section_name,
    265   struct GNUNET_TIME_Timestamp start_time,
    266   struct GNUNET_TIME_Relative validity_duration,
    267   const struct TALER_CsPubHashP *h_cs,
    268   struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub,
    269   const struct TALER_SecurityModulePublicKeyP *sm_pub,
    270   const struct TALER_SecurityModuleSignatureP *sm_sig)
    271 {
    272   struct HelperDenomination *hd;
    273 
    274   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    275               "CS helper announces key %s for denomination type %s with validity %s\n",
    276               GNUNET_h2s (&h_cs->hash),
    277               section_name,
    278               GNUNET_STRINGS_relative_time_to_string (validity_duration,
    279                                                       GNUNET_NO));
    280   TEH_keys_bump_generation ();
    281   TEH_resume_keys_requests (false);
    282   hd = GNUNET_CONTAINER_multihashmap_get (cs_keys,
    283                                           &h_cs->hash);
    284   if (NULL != hd)
    285   {
    286     /* should be just an update (revocation!), so update existing entry */
    287     hd->validity_duration = validity_duration;
    288     return;
    289   }
    290   GNUNET_assert (NULL != sm_pub);
    291   check_denom_cs_sm_pub (sm_pub);
    292   hd = GNUNET_new (struct HelperDenomination);
    293   hd->start_time = start_time;
    294   hd->validity_duration = validity_duration;
    295   hd->h_details.h_cs = *h_cs;
    296   hd->sm_sig = *sm_sig;
    297   GNUNET_assert (GNUNET_CRYPTO_BSA_CS == bs_pub->cipher);
    298   hd->denom_pub.bsign_pub_key
    299     = GNUNET_CRYPTO_bsign_pub_incref (bs_pub);
    300   /* load the age mask for the denomination, if applicable */
    301   hd->denom_pub.age_mask = TEH_CONFIG_load_age_mask (section_name);
    302   TALER_denom_pub_hash (&hd->denom_pub,
    303                         &hd->h_denom_pub);
    304   hd->section_name = GNUNET_strdup (section_name);
    305   GNUNET_assert (
    306     GNUNET_OK ==
    307     GNUNET_CONTAINER_multihashmap_put (
    308       denom_keys,
    309       &hd->h_denom_pub.hash,
    310       hd,
    311       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    312   GNUNET_assert (
    313     GNUNET_OK ==
    314     GNUNET_CONTAINER_multihashmap_put (
    315       cs_keys,
    316       &hd->h_details.h_cs.hash,
    317       hd,
    318       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    319 }
    320 
    321 
    322 /**
    323  * Check that the given EdDSA security module's public key is the one
    324  * we have pinned.  If it does not match, we die hard.
    325  *
    326  * @param sm_pub EdDSA security module public key to check
    327  */
    328 static void
    329 check_esign_sm_pub (const struct TALER_SecurityModulePublicKeyP *sm_pub)
    330 {
    331   if (0 !=
    332       GNUNET_memcmp (sm_pub,
    333                      &esign_sm_pub))
    334   {
    335     if (! GNUNET_is_zero (&esign_sm_pub))
    336     {
    337       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
    338                   "Our EdDSA security module changed its key. This must not happen.\n");
    339       GNUNET_assert (0);
    340     }
    341     esign_sm_pub = *sm_pub; /* TOFU ;-) */
    342   }
    343 }
    344 
    345 
    346 /**
    347  * Function called with information about available keys for signing.  Usually
    348  * only called once per key upon connect. Also called again in case a key is
    349  * being revoked, in that case with an @a end_time of zero.
    350  *
    351  * @param cls NULL
    352  * @param start_time when does the key become available for signing;
    353  *                 zero if the key has been revoked or purged
    354  * @param validity_duration how long does the key remain available for signing;
    355  *                 zero if the key has been revoked or purged
    356  * @param exchange_pub the public key itself, NULL if the key was revoked or purged
    357  * @param sm_pub public key of the security module, NULL if the key was revoked or purged
    358  * @param sm_sig signature from the security module
    359  */
    360 static void
    361 helper_esign_cb (
    362   void *cls,
    363   struct GNUNET_TIME_Timestamp start_time,
    364   struct GNUNET_TIME_Relative validity_duration,
    365   const struct TALER_ExchangePublicKeyP *exchange_pub,
    366   const struct TALER_SecurityModulePublicKeyP *sm_pub,
    367   const struct TALER_SecurityModuleSignatureP *sm_sig)
    368 {
    369   struct HelperSignkey *hsk;
    370   struct GNUNET_PeerIdentity pid;
    371 
    372   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
    373               "EdDSA helper announces signing key %s with validity %s\n",
    374               TALER_B2S (exchange_pub),
    375               GNUNET_STRINGS_relative_time_to_string (validity_duration,
    376                                                       GNUNET_NO));
    377   TEH_keys_bump_generation ();
    378   TEH_resume_keys_requests (false);
    379   pid.public_key = exchange_pub->eddsa_pub;
    380   hsk = GNUNET_CONTAINER_multipeermap_get (esign_keys,
    381                                            &pid);
    382   if (NULL != hsk)
    383   {
    384     /* should be just an update (revocation!), so update existing entry */
    385     hsk->validity_duration = validity_duration;
    386     return;
    387   }
    388   GNUNET_assert (NULL != sm_pub);
    389   check_esign_sm_pub (sm_pub);
    390   hsk = GNUNET_new (struct HelperSignkey);
    391   hsk->start_time = start_time;
    392   hsk->validity_duration = validity_duration;
    393   hsk->exchange_pub = *exchange_pub;
    394   hsk->sm_sig = *sm_sig;
    395   GNUNET_assert (
    396     GNUNET_OK ==
    397     GNUNET_CONTAINER_multipeermap_put (
    398       esign_keys,
    399       &pid,
    400       hsk,
    401       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
    402 }
    403 
    404 
    405 enum GNUNET_GenericReturnValue
    406 TEH_SECMOD_setup_key_helpers ()
    407 {
    408   if (GNUNET_OK !=
    409       GNUNET_CONFIGURATION_get_value_time (TEH_cfg,
    410                                            "exchange",
    411                                            "SIGNKEY_LEGAL_DURATION",
    412                                            &signkey_legal_duration))
    413   {
    414     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
    415                                "exchange",
    416                                "SIGNKEY_LEGAL_DURATION");
    417     return GNUNET_SYSERR;
    418   }
    419   denom_keys
    420     = GNUNET_CONTAINER_multihashmap_create (1024,
    421                                             GNUNET_YES);
    422   rsa_keys
    423     = GNUNET_CONTAINER_multihashmap_create (1024,
    424                                             GNUNET_YES);
    425   cs_keys
    426     = GNUNET_CONTAINER_multihashmap_create (1024,
    427                                             GNUNET_YES);
    428   esign_keys
    429     = GNUNET_CONTAINER_multipeermap_create (32,
    430                                             GNUNET_NO /* MUST BE NO! */);
    431   rsadh = TALER_CRYPTO_helper_rsa_connect (TEH_cfg,
    432                                            "taler-exchange",
    433                                            &helper_rsa_cb,
    434                                            NULL);
    435   if (NULL == rsadh)
    436     return GNUNET_SYSERR;
    437   csdh = TALER_CRYPTO_helper_cs_connect (TEH_cfg,
    438                                          "taler-exchange",
    439                                          &helper_cs_cb,
    440                                          NULL);
    441   if (NULL == csdh)
    442     return GNUNET_SYSERR;
    443   esh = TALER_CRYPTO_helper_esign_connect (TEH_cfg,
    444                                            "taler-exchange",
    445                                            &helper_esign_cb,
    446                                            NULL);
    447   if (NULL == esh)
    448     return GNUNET_SYSERR;
    449   return GNUNET_OK;
    450 }
    451 
    452 
    453 void
    454 TEH_SECMOD_sync_key_helpers (void)
    455 {
    456   TALER_CRYPTO_helper_rsa_poll (rsadh);
    457   TALER_CRYPTO_helper_cs_poll (csdh);
    458   TALER_CRYPTO_helper_esign_poll (esh);
    459 }
    460 
    461 
    462 /**
    463  * Helper function for #TEH_SECMOD_destroy_key_helpers to free all entries
    464  * in the `denom_keys` map.
    465  *
    466  * @param cls NULL
    467  * @param h_denom_pub hash of the denomination public key
    468  * @param value the `struct HelperDenomination` to release
    469  * @return #GNUNET_OK (continue to iterate)
    470  */
    471 static enum GNUNET_GenericReturnValue
    472 free_denom_cb (void *cls,
    473                const struct GNUNET_HashCode *h_denom_pub,
    474                void *value)
    475 {
    476   struct HelperDenomination *hd = value;
    477 
    478   (void) cls;
    479   (void) h_denom_pub;
    480   TALER_denom_pub_free (&hd->denom_pub);
    481   GNUNET_free (hd->section_name);
    482   GNUNET_free (hd);
    483   return GNUNET_OK;
    484 }
    485 
    486 
    487 /**
    488  * Helper function for #TEH_SECMOD_destroy_key_helpers to free all entries
    489  * in the `esign_keys` map.
    490  *
    491  * @param cls NULL
    492  * @param pid unused, matches the exchange public key
    493  * @param value the `struct HelperSignkey` to release
    494  * @return #GNUNET_OK (continue to iterate)
    495  */
    496 static enum GNUNET_GenericReturnValue
    497 free_esign_cb (void *cls,
    498                const struct GNUNET_PeerIdentity *pid,
    499                void *value)
    500 {
    501   struct HelperSignkey *hsk = value;
    502 
    503   (void) cls;
    504   (void) pid;
    505   GNUNET_free (hsk);
    506   return GNUNET_OK;
    507 }
    508 
    509 
    510 void
    511 TEH_SECMOD_destroy_key_helpers ()
    512 {
    513   GNUNET_CONTAINER_multihashmap_iterate (denom_keys,
    514                                          &free_denom_cb,
    515                                          NULL);
    516   GNUNET_CONTAINER_multihashmap_destroy (rsa_keys);
    517   rsa_keys = NULL;
    518   GNUNET_CONTAINER_multihashmap_destroy (cs_keys);
    519   cs_keys = NULL;
    520   GNUNET_CONTAINER_multihashmap_destroy (denom_keys);
    521   denom_keys = NULL;
    522   GNUNET_CONTAINER_multipeermap_iterate (esign_keys,
    523                                          &free_esign_cb,
    524                                          NULL);
    525   GNUNET_CONTAINER_multipeermap_destroy (esign_keys);
    526   esign_keys = NULL;
    527   if (NULL != rsadh)
    528   {
    529     TALER_CRYPTO_helper_rsa_disconnect (rsadh);
    530     rsadh = NULL;
    531   }
    532   if (NULL != csdh)
    533   {
    534     TALER_CRYPTO_helper_cs_disconnect (csdh);
    535     csdh = NULL;
    536   }
    537   if (NULL != esh)
    538   {
    539     TALER_CRYPTO_helper_esign_disconnect (esh);
    540     esh = NULL;
    541   }
    542 }
    543 
    544 
    545 void
    546 TEH_SECMOD_iterate_denom_keys (
    547   GNUNET_CONTAINER_MultiHashMapIteratorCallback cb,
    548   void *cb_cls)
    549 {
    550   GNUNET_CONTAINER_multihashmap_iterate (denom_keys,
    551                                          cb,
    552                                          cb_cls);
    553 }
    554 
    555 
    556 void
    557 TEH_SECMOD_iterate_esign_keys (
    558   GNUNET_CONTAINER_PeerMapIterator cb,
    559   void *cb_cls)
    560 {
    561   GNUNET_CONTAINER_multipeermap_iterate (esign_keys,
    562                                          cb,
    563                                          cb_cls);
    564 
    565 }
    566 
    567 
    568 enum TALER_ErrorCode
    569 TEH_SECMOD_denom_cs_batch_r_pub_simple (
    570   unsigned int cdds_length,
    571   const struct TEH_SECMOD_CsDeriveData cdds[static cdds_length],
    572   bool for_melt,
    573   struct GNUNET_CRYPTO_CSPublicRPairP r_pubs[static cdds_length])
    574 {
    575   struct HelperDenomination *hd;
    576   struct TALER_CRYPTO_CsDeriveRequest cdrs[cdds_length];
    577 
    578   for (unsigned int i = 0; i<cdds_length; i++)
    579   {
    580     const struct TALER_DenominationHashP *h_denom_pub = cdds[i].h_denom_pub;
    581     const struct GNUNET_CRYPTO_CsSessionNonce *nonce = cdds[i].nonce;
    582 
    583     hd = GNUNET_CONTAINER_multihashmap_get (denom_keys,
    584                                             &h_denom_pub->hash);
    585     if (NULL == hd)
    586     {
    587       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
    588     }
    589     if (GNUNET_CRYPTO_BSA_CS !=
    590         hd->denom_pub.bsign_pub_key->cipher)
    591     {
    592       return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    593     }
    594     cdrs[i].h_cs = &hd->h_details.h_cs;
    595     cdrs[i].nonce = nonce;
    596   }
    597 
    598   return TALER_CRYPTO_helper_cs_r_batch_derive (csdh,
    599                                                 cdds_length,
    600                                                 cdrs,
    601                                                 for_melt,
    602                                                 r_pubs);
    603 }
    604 
    605 
    606 enum TALER_ErrorCode
    607 TEH_SECMOD_denom_cs_batch_r_pub (
    608   size_t num,
    609   const struct TALER_DenominationHashP h_denom_pubs[static num],
    610   const struct GNUNET_CRYPTO_CsSessionNonce nonces[static num],
    611   bool for_melt,
    612   struct GNUNET_CRYPTO_CSPublicRPairP r_pubs[static num],
    613   size_t *err_idx)
    614 {
    615   struct TALER_CRYPTO_CsDeriveRequest cdrs[num];
    616 
    617   for (unsigned int i = 0; i<num; i++)
    618   {
    619     const struct TEH_DenominationKey *dk;
    620     const struct HelperDenomination *hd;
    621 
    622     *err_idx = i;
    623 
    624     /* FIXME: right now we need both,
    625      * TEH_DenominationKey and HelperDenomination,
    626      * because only TEH_DenominationKey has .recoup_possible
    627      */
    628     hd = GNUNET_CONTAINER_multihashmap_get (denom_keys,
    629                                             &h_denom_pubs[i].hash);
    630     dk = TEH_keys_denomination_by_hash (&h_denom_pubs[i],
    631                                         NULL,
    632                                         NULL);
    633     if (NULL == hd)
    634       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
    635 
    636     GNUNET_assert (NULL != dk);
    637 
    638     if (GNUNET_CRYPTO_BSA_CS !=
    639         hd->denom_pub.bsign_pub_key->cipher)
    640       return TALER_EC_EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION
    641       ;
    642 
    643     if (GNUNET_TIME_absolute_is_future (hd->start_time.abs_time))
    644       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE;
    645     if (dk->recoup_possible)
    646       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED;
    647     if (GNUNET_TIME_relative_is_zero (hd->validity_duration))
    648       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED;
    649 
    650     cdrs[i].h_cs = &hd->h_details.h_cs;
    651     cdrs[i].nonce = &nonces[i];
    652   }
    653 
    654   return TALER_CRYPTO_helper_cs_r_batch_derive (csdh,
    655                                                 num,
    656                                                 cdrs,
    657                                                 for_melt,
    658                                                 r_pubs);
    659 }
    660 
    661 
    662 enum TALER_ErrorCode
    663 TEH_SECMOD_denom_batch_sign (
    664   unsigned int csds_length,
    665   const struct TEH_SECMOD_CoinSignData csds[static csds_length],
    666   bool for_melt,
    667   struct TALER_BlindedDenominationSignature bss[static csds_length])
    668 {
    669   struct HelperDenomination *hd;
    670   struct TALER_CRYPTO_RsaSignRequest rsrs[csds_length];
    671   struct TALER_CRYPTO_CsSignRequest csrs[csds_length];
    672   struct TALER_BlindedDenominationSignature rs[csds_length];
    673   struct TALER_BlindedDenominationSignature cs[csds_length];
    674   unsigned int rsrs_pos = 0;
    675   unsigned int csrs_pos = 0;
    676   enum TALER_ErrorCode ec;
    677 
    678   for (unsigned int i = 0; i<csds_length; i++)
    679   {
    680     const struct TALER_DenominationHashP *h_denom_pub = csds[i].h_denom_pub;
    681     const struct TALER_BlindedPlanchet *bp = csds[i].bp;
    682 
    683     hd = GNUNET_CONTAINER_multihashmap_get (denom_keys,
    684                                             &h_denom_pub->hash);
    685     if (NULL == hd)
    686       return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN;
    687     if (bp->blinded_message->cipher !=
    688         hd->denom_pub.bsign_pub_key->cipher)
    689       return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    690     switch (hd->denom_pub.bsign_pub_key->cipher)
    691     {
    692     case GNUNET_CRYPTO_BSA_RSA:
    693       rsrs[rsrs_pos].h_rsa = &hd->h_details.h_rsa;
    694       rsrs[rsrs_pos].msg
    695         = bp->blinded_message->details.rsa_blinded_message.blinded_msg;
    696       rsrs[rsrs_pos].msg_size
    697         = bp->blinded_message->details.rsa_blinded_message.blinded_msg_size;
    698       rsrs_pos++;
    699       break;
    700     case GNUNET_CRYPTO_BSA_CS:
    701       csrs[csrs_pos].h_cs = &hd->h_details.h_cs;
    702       csrs[csrs_pos].blinded_planchet
    703         = &bp->blinded_message->details.cs_blinded_message;
    704       csrs_pos++;
    705       break;
    706     default:
    707       return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE;
    708     }
    709   }
    710 
    711   if (0 != rsrs_pos)
    712   {
    713     memset (rs,
    714             0,
    715             sizeof (rs));
    716   }
    717   if (0 != csrs_pos)
    718   {
    719     memset (cs,
    720             0,
    721             sizeof (cs));
    722   }
    723   ec = TALER_EC_NONE;
    724   if (0 != csrs_pos)
    725   {
    726     ec = TALER_CRYPTO_helper_cs_batch_sign (
    727       csdh,
    728       csrs_pos,
    729       csrs,
    730       for_melt,
    731       (0 == rsrs_pos) ? bss : cs);
    732     if (TALER_EC_NONE != ec)
    733     {
    734       for (unsigned int i = 0; i<csrs_pos; i++)
    735         TALER_blinded_denom_sig_free (&cs[i]);
    736       return ec;
    737     }
    738     TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_CS] += csrs_pos;
    739   }
    740   if (0 != rsrs_pos)
    741   {
    742     ec = TALER_CRYPTO_helper_rsa_batch_sign (
    743       rsadh,
    744       rsrs_pos,
    745       rsrs,
    746       (0 == csrs_pos) ? bss : rs);
    747     if (TALER_EC_NONE != ec)
    748     {
    749       for (unsigned int i = 0; i<csrs_pos; i++)
    750         TALER_blinded_denom_sig_free (&cs[i]);
    751       for (unsigned int i = 0; i<rsrs_pos; i++)
    752         TALER_blinded_denom_sig_free (&rs[i]);
    753       return ec;
    754     }
    755     TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_RSA] += rsrs_pos;
    756   }
    757 
    758   if ( (0 != csrs_pos) &&
    759        (0 != rsrs_pos) )
    760   {
    761     rsrs_pos = 0;
    762     csrs_pos = 0;
    763     for (unsigned int i = 0; i<csds_length; i++)
    764     {
    765       const struct TALER_BlindedPlanchet *bp = csds[i].bp;
    766 
    767       switch (bp->blinded_message->cipher)
    768       {
    769       case GNUNET_CRYPTO_BSA_RSA:
    770         bss[i] = rs[rsrs_pos++];
    771         break;
    772       case GNUNET_CRYPTO_BSA_CS:
    773         bss[i] = cs[csrs_pos++];
    774         break;
    775       default:
    776         GNUNET_assert (0);
    777       }
    778     }
    779   }
    780   return TALER_EC_NONE;
    781 }
    782 
    783 
    784 enum TALER_ErrorCode
    785 TEH_SECMOD_exchange_sign (
    786   const struct GNUNET_CRYPTO_SignaturePurpose *purpose,
    787   struct TALER_ExchangePublicKeyP *pub,
    788   struct TALER_ExchangeSignatureP *sig)
    789 {
    790   return TALER_CRYPTO_helper_esign_sign_ (esh,
    791                                           purpose,
    792                                           pub,
    793                                           sig);
    794 }
    795 
    796 
    797 enum GNUNET_GenericReturnValue
    798 TEH_SECMOD_denom_load_meta (
    799   const struct TALER_DenominationHashP *h_denom_pub,
    800   struct TALER_DenominationPublicKey *denom_pub,
    801   struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta)
    802 {
    803   struct HelperDenomination *hd;
    804   enum GNUNET_GenericReturnValue ok;
    805 
    806   hd = GNUNET_CONTAINER_multihashmap_get (denom_keys,
    807                                           &h_denom_pub->hash);
    808   if (NULL == hd)
    809   {
    810     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    811                 "Denomination %s not known\n",
    812                 GNUNET_h2s (&h_denom_pub->hash));
    813     return GNUNET_NO;
    814   }
    815   meta->start = hd->start_time;
    816   meta->expire_withdraw = GNUNET_TIME_absolute_to_timestamp (
    817     GNUNET_TIME_absolute_add (meta->start.abs_time,
    818                               hd->validity_duration));
    819   ok = TEH_CONFIG_load_denom_data (hd->section_name,
    820                                    meta);
    821   if (GNUNET_OK == ok)
    822   {
    823     GNUNET_assert (GNUNET_CRYPTO_BSA_INVALID !=
    824                    hd->denom_pub.bsign_pub_key->cipher);
    825     TALER_denom_pub_copy (denom_pub,
    826                           &hd->denom_pub);
    827   }
    828   else
    829   {
    830     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
    831                 "No fees for `%s', voiding key\n",
    832                 hd->section_name);
    833     memset (denom_pub,
    834             0,
    835             sizeof (*denom_pub));
    836   }
    837   return ok;
    838 }
    839 
    840 
    841 enum GNUNET_GenericReturnValue
    842 TEH_SECMOD_esign_load_meta (const struct TALER_ExchangePublicKeyP *exchange_pub,
    843                             struct TALER_EXCHANGEDB_SignkeyMetaData *meta)
    844 {
    845   struct HelperSignkey *hsk;
    846   struct GNUNET_PeerIdentity pid;
    847 
    848   pid.public_key = exchange_pub->eddsa_pub;
    849   hsk = GNUNET_CONTAINER_multipeermap_get (esign_keys,
    850                                            &pid);
    851   if (NULL == hsk)
    852   {
    853     GNUNET_break (0);
    854     return GNUNET_NO;
    855   }
    856   meta->start = hsk->start_time;
    857 
    858   meta->expire_sign = GNUNET_TIME_absolute_to_timestamp (
    859     GNUNET_TIME_absolute_add (meta->start.abs_time,
    860                               hsk->validity_duration));
    861   meta->expire_legal = GNUNET_TIME_absolute_to_timestamp (
    862     GNUNET_TIME_absolute_add (meta->expire_sign.abs_time,
    863                               signkey_legal_duration));
    864   return GNUNET_OK;
    865 }
    866 
    867 
    868 bool
    869 TEH_SECMOD_denom_priv_check_lost (
    870   const struct TALER_DenominationHashP *h_denom_pub)
    871 {
    872   struct HelperDenomination *hd;
    873 
    874   hd = GNUNET_CONTAINER_multihashmap_get (denom_keys,
    875                                           &h_denom_pub->hash);
    876   return (NULL == hd) ||
    877          GNUNET_TIME_absolute_is_past (
    878     GNUNET_TIME_absolute_add (
    879       hd->start_time.abs_time,
    880       hd->validity_duration));
    881 }
    882 
    883 
    884 void
    885 TEH_SECMOD_esign_revoke (
    886   const struct TALER_ExchangePublicKeyP *exchange_pub)
    887 {
    888   TALER_CRYPTO_helper_esign_revoke (esh,
    889                                     exchange_pub);
    890   TEH_keys_update_states ();
    891 }
    892 
    893 
    894 void
    895 TEH_SECMOD_denom_revoke (
    896   const struct TALER_DenominationHashP *h_denom_pub)
    897 {
    898   struct HelperDenomination *hd;
    899 
    900   hd = GNUNET_CONTAINER_multihashmap_get (denom_keys,
    901                                           &h_denom_pub->hash);
    902   if (NULL == hd)
    903   {
    904     GNUNET_break (0);
    905     return;
    906   }
    907   switch (hd->denom_pub.bsign_pub_key->cipher)
    908   {
    909   case GNUNET_CRYPTO_BSA_INVALID:
    910     break;
    911   case GNUNET_CRYPTO_BSA_RSA:
    912     TALER_CRYPTO_helper_rsa_revoke (rsadh,
    913                                     &hd->h_details.h_rsa);
    914     TEH_keys_update_states ();
    915     return;
    916   case GNUNET_CRYPTO_BSA_CS:
    917     TALER_CRYPTO_helper_cs_revoke (csdh,
    918                                    &hd->h_details.h_cs);
    919     TEH_keys_update_states ();
    920     return;
    921   }
    922   GNUNET_break (0);
    923   return;
    924 }