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_blinding-prepare.c (7383B)


      1 /*
      2   This file is part of TALER
      3   Copyright (C) 2025 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU Affero General Public License as
      7   published by the Free Software Foundation; either version 3,
      8   or (at your option) any later version.
      9 
     10   TALER is distributed in the hope that it will be useful,
     11   but WITHOUT ANY WARRANTY; without even the implied warranty
     12   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     13   See the GNU Affero General Public License for more details.
     14 
     15   You should have received a copy of the GNU Affero General
     16   Public License along with TALER; see the file COPYING.  If not,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 /**
     20  * @file taler-exchange-httpd_blinding-prepare.c
     21  * @brief Handle /blinding-prepare requests
     22  * @author Özgür Kesim
     23  */
     24 #include "taler/platform.h"
     25 #include <gnunet/gnunet_util_lib.h>
     26 #include <jansson.h>
     27 #include "taler/taler_json_lib.h"
     28 #include "taler/taler_mhd_lib.h"
     29 #include "taler-exchange-httpd_blinding-prepare.h"
     30 #include "taler-exchange-httpd_responses.h"
     31 #include "taler-exchange-httpd_keys.h"
     32 
     33 MHD_RESULT
     34 TEH_handler_blinding_prepare (struct TEH_RequestContext *rc,
     35                               const json_t *root,
     36                               const char *const args[])
     37 {
     38   struct TALER_BlindingMasterSeedP blinding_seed;
     39   const char *cipher;
     40   const char *operation;
     41   const json_t *j_nks;
     42   size_t num;
     43   bool is_melt;
     44   struct GNUNET_JSON_Specification spec[] = {
     45     GNUNET_JSON_spec_string ("cipher",
     46                              &cipher),
     47     GNUNET_JSON_spec_string ("operation",
     48                              &operation),
     49     GNUNET_JSON_spec_fixed_auto ("seed",
     50                                  &blinding_seed),
     51     GNUNET_JSON_spec_array_const ("nks",
     52                                   &j_nks),
     53     GNUNET_JSON_spec_end ()
     54   };
     55 
     56   (void) args;
     57   {
     58     enum GNUNET_GenericReturnValue res;
     59 
     60     res = TALER_MHD_parse_json_data (rc->connection,
     61                                      root,
     62                                      spec);
     63     if (GNUNET_OK != res)
     64       return (GNUNET_SYSERR == res)
     65         ? MHD_NO
     66         : MHD_YES;
     67   }
     68   if (0 == strcmp (operation,
     69                    "melt"))
     70   {
     71     is_melt = true;
     72   }
     73   else if (0 == strcmp (operation,
     74                         "withdraw"))
     75   {
     76     is_melt = false;
     77   }
     78   else
     79   {
     80     GNUNET_break_op (0);
     81     return TALER_MHD_reply_with_error (rc->connection,
     82                                        MHD_HTTP_BAD_REQUEST,
     83                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
     84                                        "operation");
     85   }
     86 
     87   num = json_array_size (j_nks);
     88   if ((0 == num) ||
     89       (TALER_MAX_COINS < num))
     90   {
     91     GNUNET_break_op (0);
     92     return TALER_MHD_reply_with_error (rc->connection,
     93                                        MHD_HTTP_BAD_REQUEST,
     94                                        TALER_EC_EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
     95                                        "nks");
     96   }
     97   if (0 != strcmp (cipher, "CS"))
     98   {
     99     GNUNET_break_op (0);
    100     return TALER_MHD_reply_with_error (rc->connection,
    101                                        MHD_HTTP_BAD_REQUEST,
    102                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
    103                                        " cipher");
    104   }
    105 
    106   {
    107     uint32_t cs_indices[num];
    108     struct  TALER_DenominationHashP h_denom_pubs[num];
    109     struct GNUNET_CRYPTO_CsSessionNonce nonces[num];
    110 
    111     for (size_t i = 0; i < num; i++)
    112     {
    113       enum GNUNET_GenericReturnValue res;
    114       struct GNUNET_JSON_Specification nks_spec[] = {
    115         GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
    116                                      &h_denom_pubs[i]),
    117         GNUNET_JSON_spec_uint32 ("coin_offset",
    118                                  &cs_indices[i]),
    119         GNUNET_JSON_spec_end ()
    120       };
    121 
    122       res = TALER_MHD_parse_json_array (rc->connection,
    123                                         j_nks,
    124                                         nks_spec,
    125                                         i,
    126                                         -1);
    127       if (GNUNET_OK != res)
    128         return (GNUNET_SYSERR == res)
    129           ? MHD_NO
    130           : MHD_YES;
    131 
    132       if (TALER_MAX_COINS < cs_indices[i])
    133       {
    134         GNUNET_break_op (0);
    135         return TALER_MHD_reply_with_error (rc->connection,
    136                                            MHD_HTTP_BAD_REQUEST,
    137                                            TALER_EC_GENERIC_PARAMETER_MALFORMED,
    138                                            "nks");
    139       }
    140     }
    141 
    142     TALER_cs_derive_nonces_from_seed (&blinding_seed,
    143                                       is_melt,
    144                                       num,
    145                                       cs_indices,
    146                                       nonces);
    147     {
    148       struct TEH_KeyStateHandle *ksh;
    149       struct GNUNET_CRYPTO_CSPublicRPairP r_pubs[num];
    150       size_t err_idx;
    151       enum TALER_ErrorCode ec;
    152 
    153       ksh = TEH_keys_get_state ();
    154       if (NULL == ksh)
    155         return TALER_MHD_reply_with_error (rc->connection,
    156                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
    157                                            TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
    158                                            NULL);
    159 
    160       ec =
    161         TEH_keys_denomination_cs_batch_r_pub (ksh,
    162                                               num,
    163                                               h_denom_pubs,
    164                                               nonces,
    165                                               is_melt,
    166                                               r_pubs,
    167                                               &err_idx);
    168       switch (ec)
    169       {
    170       case TALER_EC_NONE:
    171         break;
    172       case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN:
    173         return TEH_RESPONSE_reply_unknown_denom_pub_hash (
    174           rc->connection,
    175           &h_denom_pubs[err_idx]);
    176         break;
    177       case  TALER_EC_EXCHANGE_GENERIC_INVALID_DENOMINATION_CIPHER_FOR_OPERATION:
    178         return TEH_RESPONSE_reply_invalid_denom_cipher_for_operation (
    179           rc->connection,
    180           &h_denom_pubs[err_idx]);
    181         break;
    182       case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED:
    183         return TEH_RESPONSE_reply_expired_denom_pub_hash (
    184           rc->connection,
    185           &h_denom_pubs[err_idx],
    186           ec,
    187           "blinding-prepare");
    188         break;
    189       case TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE:
    190         return TEH_RESPONSE_reply_expired_denom_pub_hash (
    191           rc->connection,
    192           &h_denom_pubs[err_idx],
    193           ec,
    194           "blinding-prepare");
    195         break;
    196       default:
    197         GNUNET_break (0);
    198         return TALER_MHD_reply_with_ec (rc->connection,
    199                                         ec,
    200                                         NULL);
    201         break;
    202       }
    203 
    204       /* Finally, create the response */
    205       {
    206         struct TALER_BlindingPrepareResponse response = {
    207           .num = num,
    208           .cipher = GNUNET_CRYPTO_BSA_CS,
    209           .details.cs = r_pubs,
    210         };
    211 
    212         return TALER_MHD_REPLY_JSON_PACK (
    213           rc->connection,
    214           MHD_HTTP_OK,
    215           TALER_JSON_pack_blinding_prepare_response (NULL,
    216                                                      &response));
    217       }
    218     }
    219   }
    220 }
    221 
    222 
    223 /* end of taler-exchange-httpd_blinding_prepare.c */