frosix

Multiparty signature service (experimental)
Log | Files | Refs | README | LICENSE

frosix_api_dkg-commitment_request.c (11131B)


      1 /*
      2   This file is part of ANASTASIS
      3   Copyright (C) 2014-2019 Anastasis SARL
      4 
      5   ANASTASIS is free software; you can redistribute it and/or modify
      6   it under the terms of the GNU General Public License as
      7   published by the Free Software Foundation; either version 2.1,
      8   or (at your option) any later version.
      9 
     10   ANASTASIS is distributed in the hope that it will be useful, but
     11   WITHOUT ANY WARRANTY; without even the implied warranty of
     12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13   GNU General Public License for more details.
     14 
     15   You should have received a copy of the GNU General Public
     16   License along with ANASTASIS; see the file COPYING.LGPL.  If not,
     17   see <http://www.gnu.org/licenses/>
     18 */
     19 
     20 /**
     21  * @file restclient/frosix_api_dkg-commitment_request.c
     22  * @brief Implementation of the /dkg-commitment POST
     23  * @author Christian Grothoff
     24  * @author Dennis Neufeld
     25  * @author Dominik Meister
     26  * @author Joel Urech
     27  */
     28 #include "platform.h"
     29 #include <curl/curl.h>
     30 #include <microhttpd.h> /* just for HTTP status codes */
     31 #include "frosix_service.h"
     32 #include "frost_high.h"
     33 #include "frosix_api_curl_defaults.h"
     34 #include <gnunet/gnunet_json_lib.h>
     35 #include <taler/taler_json_lib.h>
     36 
     37 
     38 /**
     39  * @brief A commitment request operation handle
     40  */
     41 struct FROSIX_DkgCommitmentRequestOperation
     42 {
     43   /**
     44    * The url for this request, including parameters.
     45    */
     46   char *url;
     47 
     48   /**
     49    *
     50   */
     51   uint8_t provider_index;
     52 
     53   /**
     54    * Handle for the request.
     55    */
     56   struct GNUNET_CURL_Job *job;
     57 
     58   /**
     59    * The CURL context to connect to the backend
     60   */
     61   struct GNUNET_CURL_Context *ctx;
     62 
     63   /**
     64    * Function to call with the result.
     65    */
     66   FROSIX_DkgCommitmentRequestCallback cb;
     67 
     68   /**
     69    * Closure for @a cb.
     70    */
     71   void *cb_cls;
     72 };
     73 
     74 
     75 void
     76 FROSIX_dkg_commitment_request_cancel (
     77   struct FROSIX_DkgCommitmentRequestOperation *dco)
     78 {
     79   if (NULL != dco->job)
     80   {
     81     GNUNET_CURL_job_cancel (dco->job);
     82     dco->job = NULL;
     83   }
     84   GNUNET_free (dco->url);
     85   GNUNET_free (dco);
     86 }
     87 
     88 
     89 /**
     90  * Callback to process POST /dkg-commitment response
     91  *
     92  * @param cls the `struct FROSIX_DkgCommitmentRequestOperation`
     93  * @param response_code HTTP response code, 0 on error
     94  * @param data response body
     95  * @param data_size number of byte in @a data
     96 */
     97 static void
     98 handle_dkg_commitment_request_finished (void *cls,
     99                                         long response_code,
    100                                         const void *response)
    101 {
    102   struct FROSIX_DkgCommitmentRequestOperation *dco = cls;
    103   struct FROSIX_DkgCommitmentRequestDetails dcd;
    104   const json_t *json_response = response;
    105 
    106   dco->job = NULL;
    107   dcd.http_status = response_code;
    108   dcd.ec = TALER_EC_NONE;
    109 
    110   switch (response_code)
    111   {
    112   case 0:
    113     /* Hard error */
    114     GNUNET_break (0);
    115     dcd.dcs = FROSIX_DCS_HTTP_ERROR;
    116     dcd.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
    117     break;
    118   case MHD_HTTP_CREATED:
    119     {
    120       dcd.dcs = FROSIX_DCS_SUCCESS;
    121       dcd.provider_index = dco->provider_index;
    122 
    123       /* temp commitment struct */
    124       struct FROST_DkgCommitment commitment;
    125 
    126       /* We got a result, lets parse it */
    127       json_t *dkg_commitment = NULL;
    128       struct GNUNET_JSON_Specification spec[] = {
    129         GNUNET_JSON_spec_uint8 ("provider_index",
    130                                 &dcd.dkg_commitment.identifier),
    131         GNUNET_JSON_spec_json ("dkg_commitment",
    132                                &dkg_commitment),
    133         GNUNET_JSON_spec_fixed_auto ("zkp_r",
    134                                      &commitment.zkp.r),
    135         GNUNET_JSON_spec_fixed_auto ("zkp_z",
    136                                      &commitment.zkp.z),
    137         GNUNET_JSON_spec_fixed_auto ("public_key",
    138                                      &dcd.public_key),
    139         GNUNET_JSON_spec_end ()
    140       };
    141 
    142       if (GNUNET_OK !=
    143           GNUNET_JSON_parse (json_response,
    144                              spec,
    145                              NULL,
    146                              NULL))
    147       {
    148         /* Parsing failed! */
    149         GNUNET_break_op (0);
    150         dcd.http_status = 0;
    151         GNUNET_JSON_parse_free (spec);
    152         break;
    153       }
    154 
    155       /* check if number of commitment values is in allowed range */
    156       if (0 >= json_array_size (dkg_commitment)
    157           || json_array_size (dkg_commitment) >= 254)
    158       {
    159         GNUNET_break_op (0);
    160         dcd.http_status = 0;
    161         GNUNET_JSON_parse_free (spec);
    162         break;
    163       }
    164 
    165       dcd.dkg_commitment.shares_commitments_length = \
    166         (uint8_t) json_array_size (dkg_commitment);
    167 
    168       /* initialize struct dkg_commitment */
    169       FROST_initialize_dkg_commitment (
    170         &dcd.dkg_commitment,
    171         dcd.dkg_commitment.identifier,
    172         dcd.dkg_commitment.shares_commitments_length);
    173 
    174       /* copy back from temp commitment struct */
    175       memcpy (&dcd.dkg_commitment.zkp.r,
    176               &commitment.zkp.r,
    177               sizeof (commitment.zkp.r));
    178       memcpy (&dcd.dkg_commitment.zkp.z,
    179               &commitment.zkp.z,
    180               sizeof (commitment.zkp.z));
    181 
    182       /* parse commitment values */
    183       for (unsigned int i = 0; i < dcd.dkg_commitment.shares_commitments_length;
    184            i++)
    185       {
    186         struct GNUNET_JSON_Specification comm_spec[] = {
    187           GNUNET_JSON_spec_fixed_auto (NULL,
    188                                        &dcd.dkg_commitment.share_comm[i]),
    189           GNUNET_JSON_spec_end ()
    190         };
    191 
    192         if (GNUNET_OK !=
    193             GNUNET_JSON_parse (json_array_get (dkg_commitment,
    194                                                i),
    195                                comm_spec,
    196                                NULL,
    197                                NULL))
    198         {
    199           GNUNET_break_op (0);
    200           GNUNET_JSON_parse_free (comm_spec);
    201           GNUNET_JSON_parse_free (spec);
    202           FROST_free_dkg_commitment (&dcd.dkg_commitment,
    203                                      1);
    204           dcd.http_status = 0;
    205           break;
    206         }
    207 
    208         GNUNET_JSON_parse_free (comm_spec);
    209       }
    210 
    211       GNUNET_JSON_parse_free (spec);
    212       break;
    213     }
    214   case MHD_HTTP_BAD_REQUEST:
    215     /* We have a conflict with the API */
    216     GNUNET_break (0);
    217     dcd.dcs = FROSIX_DCS_CLIENT_ERROR;
    218     dcd.ec = TALER_JSON_get_error_code2 (json_response,
    219                                          json_object_size (json_response));
    220     break;
    221   case MHD_HTTP_INTERNAL_SERVER_ERROR:
    222     /* The provider has a problem! */
    223     GNUNET_break (0);
    224     dcd.dcs = FROSIX_DCS_SERVER_ERROR;
    225     dcd.ec = TALER_JSON_get_error_code2 (json_response,
    226                                          json_object_size (json_response));
    227     break;
    228   default:
    229     /* Unexpected response code */
    230     GNUNET_break (0);
    231     dcd.ec = TALER_JSON_get_error_code2 (json_response,
    232                                          json_object_size (json_response));
    233     break;
    234   }
    235 
    236   /* return to callback function with the data from the response */
    237   dco->cb (dco->cb_cls,
    238            &dcd);
    239   dco->cb = NULL;
    240 
    241   FROST_free_dkg_commitment (&dcd.dkg_commitment,
    242                              1);
    243 
    244   FROSIX_dkg_commitment_request_cancel (dco);
    245 }
    246 
    247 
    248 /**
    249  * Handle HTTP header received by curl.
    250  *
    251  * @param buffer one line of HTTP header data
    252  * @param size size of an item
    253  * @param userdata our `struct FROSIX_DkgCommitmentRequestOperation`
    254  * @return `size * nitems`
    255 */
    256 static size_t
    257 handle_header (char *buffer,
    258                size_t size,
    259                size_t nitems,
    260                void *userdata)
    261 {
    262   size_t total = size * nitems;
    263   return total;
    264 }
    265 
    266 
    267 struct FROSIX_DkgCommitmentRequestOperation *
    268 FROSIX_dkg_commitment_request (
    269   struct GNUNET_CURL_Context *ctx,
    270   const char *backend_url,
    271   const struct FROSIX_DkgRequestIdP *uuid,
    272   uint8_t identifier,
    273   uint8_t threshold,
    274   uint8_t num_of_participants,
    275   const struct FROSIX_DkgContextStringP *context_string,
    276   const struct FROSIX_ChallengeHashP *challenge_hash,
    277   const struct GNUNET_CRYPTO_EddsaPublicKey providers_public_keys[],
    278   FROSIX_DkgCommitmentRequestCallback cb,
    279   void *cb_cls)
    280 {
    281   struct FROSIX_DkgCommitmentRequestOperation *dco;
    282   CURL *eh;
    283   char *json_str;
    284 
    285   /* check if we got a callback function, abort if not */
    286   GNUNET_assert (NULL != cb);
    287 
    288   dco = GNUNET_new (struct FROSIX_DkgCommitmentRequestOperation);
    289 
    290   {
    291     /* prepare URL */
    292     char *uuid_str;
    293     char *path;
    294 
    295     uuid_str = GNUNET_STRINGS_data_to_string_alloc (uuid,
    296                                                     sizeof (*uuid));
    297 
    298     GNUNET_asprintf (&path,
    299                      "dkg-commitment/%s",
    300                      uuid_str);
    301 
    302     dco->url = TALER_url_join (backend_url,
    303                                path,
    304                                NULL);
    305 
    306     GNUNET_free (path);
    307     GNUNET_free (uuid_str);
    308   }
    309 
    310   dco->provider_index = identifier;
    311 
    312   /* array for all providers public keys */
    313   json_t *json_public_keys = json_array ();
    314 
    315 
    316   for (unsigned int i = 0; i < num_of_participants; i++)
    317   {
    318     /* single public key */
    319     json_t *public_key;
    320     public_key = GNUNET_JSON_PACK (
    321       GNUNET_JSON_pack_data_auto (NULL,
    322                                   &providers_public_keys[i]));
    323 
    324     /* add to public key array */
    325     GNUNET_assert (0 ==
    326                    json_array_append_new (
    327                      json_public_keys,
    328                      public_key));
    329   }
    330 
    331   {
    332     /* pack the json object for the request body */
    333     json_t *dkg_commitment_data;
    334     dkg_commitment_data = GNUNET_JSON_PACK (
    335       GNUNET_JSON_pack_uint64 ("provider_index",
    336                                identifier),
    337       GNUNET_JSON_pack_uint64 ("threshold",
    338                                threshold),
    339       GNUNET_JSON_pack_data_auto ("context_string",
    340                                   context_string),
    341       GNUNET_JSON_pack_data_auto ("auth_hash",
    342                                   challenge_hash),
    343       GNUNET_JSON_pack_array_steal ("providers_public_keys",
    344                                     json_public_keys));
    345     json_str = json_dumps (dkg_commitment_data,
    346                            JSON_COMPACT);
    347 
    348     json_decref (dkg_commitment_data);
    349 
    350     /* check if we have a json object, abort if it was not successful */
    351     GNUNET_assert (NULL != json_str);
    352   }
    353 
    354   /* prepare curl options and fire the request */
    355   dco->ctx = ctx;
    356   dco->cb = cb;
    357   dco->cb_cls = cb_cls;
    358 
    359   eh = FROSIX_curl_easy_get_ (dco->url);
    360 
    361   GNUNET_assert (CURLE_OK ==
    362                  curl_easy_setopt (eh,
    363                                    CURLOPT_POSTFIELDS,
    364                                    json_str));
    365   GNUNET_assert (CURLE_OK ==
    366                  curl_easy_setopt (eh,
    367                                    CURLOPT_POSTFIELDSIZE,
    368                                    strlen (json_str)));
    369   GNUNET_assert (CURLE_OK ==
    370                  curl_easy_setopt (eh,
    371                                    CURLOPT_HEADERFUNCTION,
    372                                    &handle_header));
    373   GNUNET_assert (CURLE_OK ==
    374                  curl_easy_setopt (eh,
    375                                    CURLOPT_HEADERDATA,
    376                                    dco));
    377 
    378   dco->job = GNUNET_CURL_job_add (ctx,
    379                                   eh,
    380                                   &handle_dkg_commitment_request_finished,
    381                                   dco);
    382 
    383   return dco;
    384 }