frosix

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

frosix_api_keygen.c (40002B)


      1 /*
      2   This file is part of Frosix
      3   Copyright (C) 2020, 2021 Anastasis SARL
      4 
      5   Frosix is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   Frosix 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 General Public License for more details.
     12 
     13   You should have received a copy of the GNU General Public License along with
     14   Frosix; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file reducer/frosix_api_keygen.c
     18  * @brief frosix reducer keygen api
     19  * @author Christian Grothoff
     20  * @author Dominik Meister
     21  * @author Dennis Neufeld
     22  * @author Joel Urech
     23  */
     24 
     25 #include "platform.h"
     26 #include "frosix.h"
     27 #include "frosix_api.h"
     28 #include <taler/taler_merchant_service.h>
     29 #include <time.h>
     30 
     31 #define FROSIX_KDF_CONTEXT "FROSIX-KEY"
     32 
     33 /**
     34  * FIXME
     35 */
     36 struct FROSIX_DkgProvider
     37 {
     38   /**
     39    * Name of the provider
     40   */
     41   char *provider_name;
     42 
     43   /**
     44    * URL of the provider.
     45   */
     46   char *backend_url;
     47 
     48   /**
     49    * Public provider salt
     50   */
     51   struct FROSIX_ProviderSaltP provider_salt;
     52 
     53   /**
     54    * Long term public key of the provider
     55   */
     56   struct GNUNET_CRYPTO_EddsaPublicKey provider_public_key;
     57 
     58   /**
     59    * Index of the provider
     60   */
     61   uint8_t provider_index;
     62 
     63   /**
     64    * Authentication method.
     65   */
     66   char *auth_method;
     67 
     68   /**
     69    * Authentication data.
     70   */
     71   char *auth_data;
     72 
     73   /**
     74    * Answer to the question in @e auth_data.
     75    * This field is optional and only used if authentication method is of type
     76    * security question.
     77   */
     78   char *auth_answer;
     79 
     80   /**
     81    * Context String for this provider.
     82   */
     83   struct FROSIX_DkgContextStringP context_string;
     84 
     85   /**
     86    * Salt for the hash of the authentication data
     87   */
     88   struct GNUNET_HashCode hash_salt;
     89 
     90   /**
     91    * Salted hash of the challenge data
     92   */
     93   struct FROSIX_ChallengeHashP auth_hash;
     94 
     95   /**
     96    * Commitments which we get from round 1
     97   */
     98   struct FROSIX_DkgCommitment commitment;
     99 
    100   /**
    101    * Pre encryption key
    102   */
    103   struct FROSIX_EncryptionKey pre_enc_key;
    104 
    105   /**
    106    * All the secret shares received from this provider.
    107    * Number or length of this array is always `number_of_participants - 1`
    108   */
    109   struct FROSIX_DkgSecretShare *secret_shares;
    110 
    111   /**
    112    * Public key, should be the same at all providers
    113   */
    114   struct FROST_PublicKey public_key;
    115 
    116   /**
    117    * Provider's signature over public key and authentication data.
    118   */
    119   struct GNUNET_CRYPTO_EddsaSignature providers_signature;
    120 
    121   /**
    122    * Seed of provider
    123   */
    124   uint8_t seed[64];
    125 };
    126 
    127 
    128 /**
    129  * Struct to store all parsed data from the cli and /config and /seed
    130 */
    131 struct FROSIX_DkgData
    132 {
    133   /**
    134    * What is the threshold value?
    135   */
    136   uint8_t threshold;
    137 
    138   /**
    139    * Number of participating providers. Is the length of the @e providers array
    140   */
    141   uint8_t num_of_participants;
    142 
    143   /**
    144    * Our master key we have to export at the end of the DKG.
    145   */
    146   struct GNUNET_HashCode master_key;
    147 
    148   /**
    149    * Pointer to a list of providers
    150   */
    151   struct FROSIX_DkgProvider *providers;
    152 
    153   /**
    154    * Array of the public keys from all providers.
    155    * Length is @e num_of_participants
    156   */
    157   struct GNUNET_CRYPTO_EddsaPublicKey *providers_public_keys;
    158 
    159   /**
    160    * Number of years the key data should be stored at the providers.
    161   */
    162   uint64_t expiration;
    163 };
    164 
    165 
    166 /**
    167  * State of a keygen procedure
    168 */
    169 struct FROSIX_DkgState
    170 {
    171   /**
    172    * State we are updating.
    173    */
    174   struct FROSIX_DkgData *dkg_data;
    175 
    176   /**
    177    * Function to call when we are done.
    178    */
    179   FROSIX_ActionCallback cb;
    180 
    181   /**
    182    * Closure for @e cb.
    183    */
    184   void *cb_cls;
    185 
    186   /**
    187    * Redux action we returned to our controller.
    188    */
    189   struct FROSIX_ReduxAction ra;
    190 
    191   /**
    192    * Number of provider operations that are still awaiting completion.
    193    */
    194   uint8_t counter;
    195 
    196   /**
    197    * Last error code
    198   */
    199   enum TALER_ErrorCode error_code;
    200 
    201   /**
    202     * Array of config requests, with length `num_of_participants`
    203   */
    204   struct FROSIX_ConfigOperation **co;
    205 
    206   /**
    207    * Array of seed requests, with length `num_of_participants`
    208   */
    209   struct FROSIX_SeedGetOperation **sgo;
    210 
    211   /**
    212    * DKG-Commitment Requests
    213   */
    214   struct FROSIX_DkgCommitmentRequestOperation **dco;
    215 
    216   /**
    217    * DKG-Share Requests
    218   */
    219   struct FROSIX_DkgShareRequestOperation **dso;
    220 
    221   /**
    222    * DKG-Key Requests
    223   */
    224   struct FROSIX_DkgKeyStoreOperation **dko;
    225 };
    226 
    227 
    228 /**
    229  * Helper function to free all initialized memory of a
    230  * `struct FROSIX_DkgProvider`
    231  *
    232  * @param dp Pointer to the provider we want to free the memory.
    233 */
    234 static void
    235 free_dkg_provider_struct (struct FROSIX_DkgProvider *dp)
    236 {
    237   if (NULL != dp->provider_name)
    238     GNUNET_free (dp->provider_name);
    239 
    240   if (NULL != dp->backend_url)
    241     GNUNET_free (dp->backend_url);
    242 
    243   if (NULL != dp->auth_method)
    244     GNUNET_free (dp->auth_method);
    245 
    246   if (NULL != dp->auth_data)
    247     GNUNET_free (dp->auth_data);
    248 
    249   if (NULL != dp->auth_answer)
    250     GNUNET_free (dp->auth_answer);
    251 
    252   FROST_free_dkg_commitment (&dp->commitment.commitment,
    253                              1);
    254 
    255   if (NULL != dp->secret_shares)
    256     GNUNET_free (dp->secret_shares);
    257 }
    258 
    259 
    260 /**
    261  * Function to free all initialized memory of a provider from a
    262  * `struct FROSIX_DkgData`
    263  *
    264  * @param dd the struct to clean up
    265 */
    266 static void
    267 free_dkg_data_struct (struct FROSIX_DkgData *dd)
    268 {
    269   /* go through all providers - if any */
    270   if (NULL != dd->providers)
    271   {
    272     for (unsigned int i = 0; i < dd->num_of_participants; i++)
    273     {
    274       if (NULL != &dd->providers[i])
    275         free_dkg_provider_struct (&dd->providers[i]);
    276     }
    277     GNUNET_free (dd->providers);
    278   }
    279 
    280   if (NULL != dd->providers_public_keys)
    281     GNUNET_free (dd->providers_public_keys);
    282 }
    283 
    284 
    285 /**
    286  * Function called when keygen is being aborted.
    287  * Frees all initialized memory!
    288  *
    289  * @param cls a `struct FROSIX_DkgState`
    290 */
    291 static void
    292 keygen_cancel_cb (void *cls)
    293 {
    294   struct FROSIX_DkgState *ds = cls;
    295 
    296   /* free dkg data */
    297   if (NULL != ds->dkg_data)
    298   {
    299     free_dkg_data_struct (ds->dkg_data);
    300     GNUNET_free (ds->dkg_data);
    301   }
    302 
    303   /* free operations */
    304   if (NULL != ds->co)
    305     GNUNET_free (ds->co);
    306 
    307   if (NULL != ds->sgo)
    308     GNUNET_free (ds->sgo);
    309 
    310   if (NULL != ds->dco)
    311     GNUNET_free (ds->dco);
    312 
    313   if (NULL != ds->dso)
    314     GNUNET_free (ds->dso);
    315 
    316   if (NULL != ds->dko)
    317     GNUNET_free (ds->dko);
    318 
    319   /* free dkg state */
    320   GNUNET_free (ds);
    321 }
    322 
    323 
    324 /**
    325  * FIXME: move to frosix common crypto functions library!
    326 */
    327 static void
    328 derive_encryption_key (
    329   struct FROSIX_EncryptionKey *enc_key,
    330   const struct FROSIX_EncryptionKey *pre_enc_key,
    331   const struct FROST_PublicKey *pk,
    332   const struct FROSIX_ProviderSaltP *provider_salt,
    333   uint8_t provider_index)
    334 {
    335   GNUNET_CRYPTO_kdf (enc_key,
    336                      sizeof (*enc_key),
    337                      FROSIX_KDF_CONTEXT,
    338                      sizeof (FROSIX_KDF_CONTEXT),
    339                      pre_enc_key,
    340                      sizeof (*pre_enc_key),
    341                      pk,
    342                      sizeof (*pk),
    343                      provider_salt,
    344                      sizeof (*provider_salt),
    345                      &provider_index,
    346                      sizeof (provider_index),
    347                      NULL,
    348                      0);
    349 }
    350 
    351 /**
    352  * Helper function to build an array out of all provider public keys.
    353  * The assembled array is then stored in our @a dd struct.
    354  *
    355  * @param dd Our main struct to store all relevant data in.
    356 */
    357 static void
    358 keygen_build_public_key_array (struct FROSIX_DkgData *dd)
    359 {
    360   /* prepare array of providers public keys */
    361   dd->providers_public_keys = GNUNET_malloc (
    362     dd->num_of_participants
    363     * sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
    364 
    365   GNUNET_assert (NULL != dd->providers_public_keys);
    366 
    367   for (unsigned int i = 0; i < dd->num_of_participants; i++)
    368   {
    369     memcpy (&dd->providers_public_keys[i],
    370             &dd->providers[i].provider_public_key,
    371             sizeof (dd->providers->provider_public_key));
    372   }
    373 }
    374 
    375 
    376 /**
    377  * This function gets called after we have received a positive result from all
    378  * providers. It prepares a json struct, which we then return back to the cli.
    379  *
    380  * @param ds The state of our keygen process.
    381 */
    382 static void
    383 keygen_prepare_result (struct FROSIX_DkgState *ds)
    384 {
    385   /* first check if signature from providers can be verified. */
    386   // FIXME: define constant for size of ps struct
    387   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
    388   {
    389     struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[i];
    390 
    391     struct FROSIX_DkgKeySignaturePS ks = {
    392       .purpose.purpose = htonl (104),
    393       .purpose.size = htonl (sizeof (ks)),
    394       .public_key = dp->public_key,
    395       .auth_hash = dp->auth_hash,
    396     };
    397 
    398     GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_verify (
    399                      104,
    400                      &ks,
    401                      &dp->providers_signature,
    402                      &dp->provider_public_key));
    403   }
    404 
    405   /* check if every reported public key is the same */
    406   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
    407   {
    408     if (GNUNET_OK != FROST_point_cmp (
    409           &ds->dkg_data->providers[i].public_key.pk,
    410           &ds->dkg_data->providers[0].public_key.pk))
    411     {
    412       json_t *error_message;
    413       error_message = GNUNET_JSON_PACK (
    414         GNUNET_JSON_pack_string ("Frosix_client_error",
    415                                  "Public keys do not match"));
    416 
    417       ds->cb (ds->cb_cls,
    418               0,
    419               error_message);
    420 
    421       return;
    422     }
    423   }
    424 
    425   /* calculate encryption keys */
    426   struct FROSIX_EncryptionKey enc_keys[ds->dkg_data->num_of_participants];
    427   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
    428   {
    429     struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[i];
    430     derive_encryption_key (&enc_keys[i],
    431                            &dp->pre_enc_key,
    432                            &dp->public_key,
    433                            &dp->provider_salt,
    434                            dp->provider_index);
    435   }
    436 
    437   /* build json */
    438   json_t *result;
    439   json_t *providers = json_array ();
    440 
    441   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
    442   {
    443     /* build single provider */
    444     struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[i];
    445     json_t *provider;
    446     provider = GNUNET_JSON_PACK (
    447       GNUNET_JSON_pack_uint64 ("provider_index",
    448                                dp->provider_index),
    449       GNUNET_JSON_pack_string ("provider_name",
    450                                dp->provider_name),
    451       GNUNET_JSON_pack_string ("backend_url",
    452                                dp->backend_url),
    453       GNUNET_JSON_pack_data_auto ("encryption_key",
    454                                   &enc_keys[i]),
    455       GNUNET_JSON_pack_string ("auth_method",
    456                                dp->auth_method),
    457       GNUNET_JSON_pack_string ("auth_data",
    458                                dp->auth_data),
    459       GNUNET_JSON_pack_data_auto ("auth_nonce",
    460                                   &dp->hash_salt),
    461       GNUNET_JSON_pack_data_auto ("auth_hash",
    462                                   &dp->auth_hash),
    463       GNUNET_JSON_pack_data_auto ("provider_signature",
    464                                   &dp->providers_signature),
    465       GNUNET_JSON_pack_data_auto ("provider_public_key",
    466                                   &dp->provider_public_key));
    467 
    468     /* add to provider array */
    469     GNUNET_assert (0 ==
    470                    json_array_append_new (
    471                      providers,
    472                      provider));
    473   }
    474 
    475   result = GNUNET_JSON_PACK (
    476     GNUNET_JSON_pack_data_auto ("public_key",
    477                                 &ds->dkg_data->providers[0].public_key),
    478     GNUNET_JSON_pack_uint64 ("number_of_participants",
    479                              ds->dkg_data->num_of_participants),
    480     GNUNET_JSON_pack_uint64 ("threshold",
    481                              ds->dkg_data->threshold),
    482     GNUNET_JSON_pack_array_steal ("providers",
    483                                   providers));
    484 
    485   /* free all initialized data */
    486   free_dkg_data_struct (ds->dkg_data);
    487 
    488   ds->cb (ds->cb_cls,
    489           ds->error_code,
    490           result);
    491 }
    492 
    493 
    494 /**
    495  * Callback to process a POST /dkg-key request
    496  *
    497  * @param cls closure
    498  * @param dcd the decoded response body
    499 */
    500 static void
    501 dkg_key_request_cb (void *cls,
    502                     const struct FROSIX_DkgKeyStoreDetails *dkd)
    503 {
    504   GNUNET_assert (NULL != cls);
    505   struct FROSIX_DkgState *ds = cls;
    506 
    507   if (0 >= ds->counter)
    508   {
    509     /* We haven't expected this callback, thus just ignore it */
    510     return;
    511   }
    512 
    513   /* check if the call was successful */
    514   if (0 == dkd->http_status)
    515   {
    516     ds->counter = 0;
    517 
    518     // FIXME: cancel all other running and not yet returned requests
    519     json_t *error_message;
    520     error_message = GNUNET_JSON_PACK (
    521       GNUNET_JSON_pack_string ("Frosix_client_error",
    522                                "Error requesting dkg key from provider"));
    523 
    524     ds->cb (ds->cb_cls,
    525             0,
    526             error_message);
    527 
    528     return;
    529   }
    530 
    531   /* set error code */
    532   ds->error_code = dkd->ec;
    533 
    534   /* check if provider index is valid */
    535   GNUNET_assert (0 < dkd->provider_index);
    536   GNUNET_assert (ds->dkg_data->num_of_participants >= dkd->provider_index);
    537 
    538   /* copy commitment in our struct - just assign pointer */
    539   struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[dkd->provider_index
    540                                                            - 1];
    541 
    542   memcpy (&dp->public_key,
    543           &dkd->details.public_key,
    544           sizeof (dkd->details.public_key));
    545 
    546   memcpy (&dp->providers_signature,
    547           &dkd->details.signature,
    548           sizeof (dkd->details.signature));
    549 
    550   /* call next dkg-commitment request */
    551   ds->counter--;
    552   if (0 == ds->counter)
    553   {
    554     /* we are the last, go ahead with checking our result */
    555     GNUNET_free (ds->dko);
    556     ds->dko = NULL;
    557     keygen_prepare_result (ds);
    558   }
    559 }
    560 
    561 
    562 /**
    563  * FIXME
    564 */
    565 static void
    566 start_dkg_key (struct FROSIX_DkgState *ds)
    567 {
    568   ds->dko = GNUNET_malloc (ds->dkg_data->num_of_participants * sizeof (char *));
    569   ds->counter = 0;
    570 
    571   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
    572   {
    573     struct FROSIX_DkgData *dd = ds->dkg_data;
    574     struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[i];
    575 
    576     /* set up array of secret shares */
    577     struct FROSIX_DkgKeyStoreShare secret_shares[dd->num_of_participants - 1];
    578 
    579     for (unsigned int j = 0; j < dd->num_of_participants; j++)
    580     {
    581       if (j < i)
    582       {
    583         /* check if target of the secret share matches */
    584         if (dp->provider_index != dd->providers[j].secret_shares[i - 1].target)
    585         {
    586           json_t *error_message;
    587           error_message = GNUNET_JSON_PACK (
    588             GNUNET_JSON_pack_string ("Frosix_client_error",
    589                                      "Error while assigning the secret shares"));
    590 
    591           ds->cb (ds->cb_cls,
    592                   0,
    593                   error_message);
    594 
    595           return;
    596         }
    597 
    598         secret_shares[j].identifier =
    599           dd->providers[j].secret_shares[i - 1].issuer;
    600 
    601         memcpy (&secret_shares[j].secret_share,
    602                 &dd->providers[j].secret_shares[i - 1].encrypted_share,
    603                 sizeof (dd->providers[j].secret_shares[i - 1].encrypted_share));
    604         memcpy (&secret_shares[j].ephemeral_key,
    605                 &dd->providers[j].secret_shares[i - 1].ephemeral_key,
    606                 sizeof (dd->providers[j].secret_shares[i - 1].ephemeral_key));
    607       }
    608       else if (j > i)
    609       {
    610         /* check if target of the secret share matches */
    611         if (dp->provider_index != dd->providers[j].secret_shares[i].target)
    612         {
    613           json_t *error_message;
    614           error_message = GNUNET_JSON_PACK (
    615             GNUNET_JSON_pack_string ("Frosix_client_error",
    616                                      "Error while assigning the secret shares"));
    617 
    618           ds->cb (ds->cb_cls,
    619                   0,
    620                   error_message);
    621 
    622           return;
    623         }
    624 
    625         secret_shares[j - 1].identifier =
    626           dd->providers[j].secret_shares[i].issuer;
    627         memcpy (&secret_shares[j - 1].secret_share,
    628                 &dd->providers[j].secret_shares[i].encrypted_share,
    629                 sizeof (dd->providers[j].secret_shares[i].encrypted_share));
    630         memcpy (&secret_shares[j - 1].ephemeral_key,
    631                 &dd->providers[j].secret_shares[i].ephemeral_key,
    632                 sizeof (dd->providers[j].secret_shares[i].ephemeral_key));
    633       }
    634     }
    635 
    636     /* compute request id */
    637     struct FROSIX_DkgRequestIdP request_id;
    638     FROSIX_compute_dkg_request_id (
    639       &request_id,
    640       &dp->context_string,
    641       &dp->auth_hash,
    642       &dp->provider_salt,
    643       dp->provider_index,
    644       ds->dkg_data->num_of_participants,
    645       ds->dkg_data->threshold);
    646 
    647     ds->dko[i] = FROSIX_dkg_key_store (
    648       FROSIX_REDUX_ctx_,
    649       dp->backend_url,
    650       &request_id,
    651       dp->provider_index,
    652       dd->threshold,
    653       dd->num_of_participants,
    654       &dp->context_string,
    655       &dp->auth_hash,
    656       dd->providers_public_keys,
    657       &dp->pre_enc_key,
    658       dd->expiration,
    659       secret_shares,
    660       dd->num_of_participants - 1,
    661       &dkg_key_request_cb,
    662       ds);
    663 
    664     ds->counter++;
    665   }
    666 }
    667 
    668 
    669 /**
    670  * Callback to process a POST /dkg-shares request
    671  *
    672  * @param cls closure
    673  * @param dcd the decoded response body
    674 */
    675 static void
    676 dkg_share_request_cb (void *cls,
    677                       const struct FROSIX_DkgShareRequestDetails *dsd)
    678 {
    679   GNUNET_assert (NULL != cls);
    680   struct FROSIX_DkgState *ds = cls;
    681 
    682   if (0 >= ds->counter)
    683   {
    684     /* We haven't expected this callback, thus just ignore it */
    685     return;
    686   }
    687 
    688   /* check if the call was successful */
    689   if (0 == dsd->http_status)
    690   {
    691     ds->counter = 0;
    692 
    693     // FIXME: cancel all other running and not yet returned requests
    694     json_t *error_message;
    695     error_message = GNUNET_JSON_PACK (
    696       GNUNET_JSON_pack_string ("Frosix_client_error",
    697                                "Error requesting dkg shares from provider"));
    698 
    699     ds->cb (ds->cb_cls,
    700             0,
    701             error_message);
    702 
    703     return;
    704   }
    705 
    706   /* set error code */
    707   ds->error_code = dsd->ec;
    708 
    709   /* check if provider index is valid */
    710   GNUNET_assert (0 < dsd->provider_index);
    711   GNUNET_assert (ds->dkg_data->num_of_participants >= dsd->provider_index);
    712 
    713   /* check number of secret shares */
    714   if (ds->dkg_data->num_of_participants - 1 != dsd->shares_len)
    715   {
    716     ds->counter = 0;
    717 
    718     // FIXME: cancel all other running and not yet returned requests
    719     json_t *error_message;
    720     error_message = GNUNET_JSON_PACK (
    721       GNUNET_JSON_pack_string ("Frosix_client_error",
    722                                "Error in dkg shares response"));
    723 
    724     ds->cb (ds->cb_cls,
    725             0,
    726             error_message);
    727 
    728     return;
    729   }
    730 
    731   /* check if our provider index is same as in the response */
    732   for (unsigned int i = 0; i < dsd->shares_len; i++)
    733   {
    734     if (dsd->provider_index != dsd->shares[i].issuer)
    735     {
    736       ds->counter = 0;
    737 
    738       // FIXME: cancel all other running and not yet returned requests
    739       json_t *error_message;
    740       error_message = GNUNET_JSON_PACK (
    741         GNUNET_JSON_pack_string ("Frosix_client_error",
    742                                  "Error in dkg shares response"));
    743 
    744       ds->cb (ds->cb_cls,
    745               0,
    746               error_message);
    747 
    748       return;
    749     }
    750   }
    751 
    752   /* copy commitment in our struct - just assign pointer */
    753   ds->dkg_data->providers[dsd->provider_index - 1].secret_shares = dsd->shares;
    754 
    755   /* call next dkg-commitment request */
    756   ds->counter--;
    757   if (0 == ds->counter)
    758   {
    759     /* we are the last, go ahead with dkg-key */
    760     GNUNET_free (ds->dso);
    761     ds->dso = NULL;
    762     start_dkg_key (ds);
    763   }
    764 }
    765 
    766 
    767 /**
    768  * FIXME
    769 */
    770 static void
    771 start_dkg_shares (struct FROSIX_DkgState *ds)
    772 {
    773   ds->dso = GNUNET_malloc (ds->dkg_data->num_of_participants * sizeof (char *));
    774   ds->counter = 0;
    775 
    776   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
    777   {
    778     struct FROSIX_DkgData *dd = ds->dkg_data;
    779     struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[i];
    780 
    781     /* set up array of dkg commitments */
    782     struct FROSIX_DkgCommitment dkg_commitments[dd->num_of_participants - 1];
    783     for (unsigned int j = 0; j < dd->num_of_participants; j++)
    784     {
    785       if (j < i)
    786       {
    787         dkg_commitments[j] = dd->providers[j].commitment;
    788       }
    789       else if (j > i)
    790       {
    791         dkg_commitments[j - 1] = dd->providers[j].commitment;
    792       }
    793     }
    794 
    795     /* compute request id */
    796     struct FROSIX_DkgRequestIdP request_id;
    797     FROSIX_compute_dkg_request_id (
    798       &request_id,
    799       &dp->context_string,
    800       &dp->auth_hash,
    801       &dp->provider_salt,
    802       dp->provider_index,
    803       ds->dkg_data->num_of_participants,
    804       ds->dkg_data->threshold);
    805 
    806     ds->dso[i] = FROSIX_dkg_share_request (
    807       FROSIX_REDUX_ctx_,
    808       dp->backend_url,
    809       &request_id,
    810       dp->provider_index,
    811       dd->threshold,
    812       dd->num_of_participants,
    813       &dp->context_string,
    814       &dp->auth_hash,
    815       dkg_commitments,
    816       dd->num_of_participants - 1,
    817       dd->providers_public_keys,
    818       &dkg_share_request_cb,
    819       ds);
    820 
    821     ds->counter++;
    822   }
    823 
    824   /* free dkg commitments */
    825   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
    826   {
    827     FROST_free_dkg_commitment (
    828       &ds->dkg_data->providers[i].commitment.commitment,
    829       1);
    830   }
    831 }
    832 
    833 
    834 /**
    835  * Callback to process a POST /dkg-commitment request
    836  *
    837  * @param cls closure
    838  * @param dcd the decoded response body
    839 */
    840 static void
    841 dkg_commitment_request_cb (void *cls,
    842                            const struct FROSIX_DkgCommitmentRequestDetails *dcd)
    843 {
    844   GNUNET_assert (NULL != cls);
    845   struct FROSIX_DkgState *ds = cls;
    846 
    847   if (0 >= ds->counter)
    848   {
    849     /* We haven't expected this callback, thus just ignore it */
    850     return;
    851   }
    852 
    853   /* check if the call was successful */
    854   if (0 == dcd->http_status)
    855   {
    856     ds->counter = 0;
    857 
    858     // FIXME: cancel all other running and not yet returned requests
    859     json_t *error_message;
    860     error_message = GNUNET_JSON_PACK (
    861       GNUNET_JSON_pack_string ("Frosix_client_error",
    862                                "Error requesting dkg commitment from provider"));
    863 
    864     ds->cb (ds->cb_cls,
    865             0,
    866             error_message);
    867 
    868     return;
    869   }
    870 
    871   /* set error code */
    872   ds->error_code = dcd->ec;
    873 
    874   /* check if provider index is valid */
    875   GNUNET_assert (0 < dcd->provider_index);
    876   GNUNET_assert (ds->dkg_data->num_of_participants >= dcd->provider_index);
    877 
    878   /* check if our provider index is same as in the response */
    879   if (dcd->provider_index != dcd->dkg_commitment.identifier)
    880   {
    881     ds->counter--;
    882 
    883     // FIXME: cancel all other running and not yet returned requests
    884     json_t *error_message;
    885     error_message = GNUNET_JSON_PACK (
    886       GNUNET_JSON_pack_string ("Frosix_client_error",
    887                                "Error in dkg commitment response"));
    888 
    889     ds->cb (ds->cb_cls,
    890             0,
    891             error_message);
    892 
    893     return;
    894   }
    895 
    896   /* check if length of commitments equals our threshold value */
    897   if (dcd->dkg_commitment.shares_commitments_length != ds->dkg_data->threshold)
    898   {
    899     ds->counter = 0;
    900 
    901     // FIXME: cancel all other running and not yet returned requests
    902     json_t *error_message;
    903     error_message = GNUNET_JSON_PACK (
    904       GNUNET_JSON_pack_string ("Frosix_client_error",
    905                                "Error in dkg commitment response"));
    906 
    907     ds->cb (ds->cb_cls,
    908             0,
    909             error_message);
    910 
    911     return;
    912   }
    913 
    914   /* copy commitment in our struct */
    915   struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[dcd->provider_index
    916                                                            - 1];
    917 
    918   /* Fill return values in our central struct */
    919   memcpy (&dp->commitment.encryption_public_key,
    920           &dcd->public_key,
    921           sizeof (dcd->public_key));
    922 
    923   FROST_initialize_dkg_commitment (
    924     &dp->commitment.commitment,
    925     dcd->provider_index,
    926     dcd->dkg_commitment.shares_commitments_length);
    927 
    928   for (unsigned int i = 0; i < dcd->dkg_commitment.shares_commitments_length;
    929        i++)
    930   {
    931     memcpy (&dp->commitment.commitment.share_comm[i],
    932             &dcd->dkg_commitment.share_comm[i],
    933             sizeof (dcd->dkg_commitment.share_comm[i]));
    934   }
    935 
    936   memcpy (&dp->commitment.commitment.zkp.r,
    937           &dcd->dkg_commitment.zkp.r,
    938           sizeof (dcd->dkg_commitment.zkp.r));
    939 
    940   memcpy (&dp->commitment.commitment.zkp.z,
    941           &dcd->dkg_commitment.zkp.z,
    942           sizeof (dcd->dkg_commitment.zkp.z));
    943 
    944   /* call next dkg-commitment request */
    945   ds->counter--;
    946   if (0 == ds->counter)
    947   {
    948     /* we are the last, go ahead with dkg-share */
    949     GNUNET_free (ds->dco);
    950     ds->dco = NULL;
    951     start_dkg_shares (ds);
    952   }
    953 }
    954 
    955 
    956 /**
    957  * Function to derive the master key and all context strings.
    958  *
    959  * @param[in,out] dd the struct to fill in the entropy
    960  * @param[in] client_entropy high entropy bytes to derive more high entropy bytes
    961 */
    962 static void
    963 keygen_derive_entropy (struct FROSIX_DkgData *dd,
    964                        const struct GNUNET_HashCode *client_entropy,
    965                        const struct GNUNET_HashCode *provider_entropy)
    966 {
    967   {
    968     /* derive high entropy bytes */
    969     size_t length = sizeof (dd->master_key)
    970                     + (dd->num_of_participants
    971                        * sizeof (dd->providers->context_string));
    972 
    973     char *derived_entropy = GNUNET_malloc (length);
    974 
    975     /* kill process if allocation failed */
    976     GNUNET_assert (NULL != derived_entropy);
    977 
    978     GNUNET_assert (GNUNET_CRYPTO_kdf (derived_entropy,
    979                                       length,
    980                                       "FROSIX",
    981                                       strlen ("FROSIX"),
    982                                       client_entropy,
    983                                       sizeof (*client_entropy),
    984                                       provider_entropy,
    985                                       sizeof (*provider_entropy),
    986                                       NULL,
    987                                       0));
    988 
    989     /* copy the derived bytes to the right place */
    990     unsigned int byte_counter = 0;
    991     memcpy (&dd->master_key,
    992             &derived_entropy[byte_counter],
    993             sizeof (dd->master_key));
    994     byte_counter += sizeof (dd->master_key);
    995 
    996     for (unsigned int i = 0; i < dd->num_of_participants; i++)
    997     {
    998       memcpy (&dd->providers[i].context_string,
    999               &derived_entropy[byte_counter],
   1000               sizeof (dd->providers->context_string));
   1001       byte_counter += sizeof (dd->providers->context_string);
   1002     }
   1003 
   1004     /* free allocated memory */
   1005     GNUNET_free (derived_entropy);
   1006   }
   1007 
   1008   {
   1009     /* derive authentication salts and pre encryption keys */
   1010     size_t length = dd->num_of_participants
   1011                     * (sizeof (dd->providers->hash_salt)
   1012                        + sizeof (dd->providers->pre_enc_key));
   1013 
   1014     char *client_entropy = GNUNET_malloc (length);
   1015 
   1016     /* kill process if allocation failed */
   1017     GNUNET_assert (NULL != client_entropy);
   1018 
   1019     GNUNET_CRYPTO_kdf (client_entropy,
   1020                        length,
   1021                        "FROSIX",
   1022                        strlen ("FROSIX"),
   1023                        &dd->master_key,
   1024                        sizeof (dd->master_key),
   1025                        NULL,
   1026                        0);
   1027 
   1028     /* copy bytes to the right place */
   1029     unsigned int byte_counter = 0;
   1030     for (unsigned int i = 0; i < dd->num_of_participants; i++)
   1031     {
   1032       memcpy (&dd->providers[i].hash_salt,
   1033               &client_entropy[byte_counter],
   1034               sizeof (dd->providers->hash_salt));
   1035       byte_counter += sizeof (dd->providers->hash_salt);
   1036     }
   1037 
   1038     for (unsigned int i = 0; i < dd->num_of_participants; i++)
   1039     {
   1040       memcpy (&dd->providers[i].pre_enc_key,
   1041               &client_entropy[byte_counter],
   1042               sizeof (dd->providers->pre_enc_key));
   1043       byte_counter += sizeof (dd->providers->pre_enc_key);
   1044     }
   1045 
   1046     /* free allocated memory */
   1047     GNUNET_free (client_entropy);
   1048   }
   1049 }
   1050 
   1051 
   1052 /**
   1053  * FIXME
   1054 */
   1055 static void
   1056 merge_provider_entropy (struct GNUNET_HashCode *provider_entropy,
   1057                         const struct FROSIX_DkgState *ds)
   1058 {
   1059   struct GNUNET_HashContext *hc = GNUNET_CRYPTO_hash_context_start ();
   1060   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
   1061   {
   1062     GNUNET_CRYPTO_hash_context_read (hc,
   1063                                      ds->dkg_data->providers[i].seed,
   1064                                      sizeof (ds->dkg_data->providers[i].seed));
   1065   }
   1066 
   1067   GNUNET_CRYPTO_hash_context_finish (hc,
   1068                                      provider_entropy);
   1069 }
   1070 
   1071 
   1072 /**
   1073  * FIXME
   1074 */
   1075 static void
   1076 start_dkg_commitments (struct FROSIX_DkgState *ds)
   1077 {
   1078   /* measure cpu speed */
   1079   // unsigned int target_difficulty = 5000; // FIXME
   1080   unsigned int amplifier = 1;
   1081   {
   1082     struct FROST_PowSalt salt;
   1083     GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
   1084                                 &salt,
   1085                                 sizeof (salt));
   1086 
   1087     /* start */
   1088     // clock_t start = clock ();
   1089     struct FROST_HashCode hash;
   1090     FROST_pow_hash (&hash,
   1091                     "Frosix",
   1092                     strlen ("Frosix"),
   1093                     &salt,
   1094                     1);
   1095     /* end */
   1096     // clock_t end = clock ();
   1097     // float seconds = (float) (end - start) / 1000;
   1098     // amplifier = target_difficulty / seconds;
   1099 
   1100   }
   1101 
   1102   /* merge provider seeds to a single hash code */
   1103   struct GNUNET_HashCode provider_entropy;
   1104   merge_provider_entropy (&provider_entropy,
   1105                           ds);
   1106 
   1107   /* derive master key, context strings, salts and pre encryption keys */
   1108   struct GNUNET_HashCode client_entropy;
   1109   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
   1110                               &client_entropy,
   1111                               sizeof (client_entropy));
   1112 
   1113   keygen_derive_entropy (ds->dkg_data,
   1114                          &client_entropy,
   1115                          &provider_entropy);
   1116 
   1117   /* compute salted hash of authentication data */
   1118   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
   1119   {
   1120     struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[i];
   1121     if (NULL != dp->auth_answer)
   1122     {
   1123       /* we have a security question here */
   1124       struct GNUNET_CRYPTO_Edx25519PrivateKey priv;
   1125       struct GNUNET_CRYPTO_Edx25519PublicKey pub;
   1126       FROSIX_hash_pow (&dp->auth_hash.hash,
   1127                        &priv,
   1128                        &pub,
   1129                        &dp->hash_salt,
   1130                        dp->auth_answer,
   1131                        amplifier);
   1132     }
   1133     else
   1134     {
   1135       FROSIX_compute_auth_hash (&dp->auth_hash,
   1136                                 dp->auth_data,
   1137                                 &dp->hash_salt);
   1138     }
   1139   }
   1140 
   1141   ds->dco = GNUNET_malloc (ds->dkg_data->num_of_participants * sizeof (char *));
   1142   ds->counter = 0;
   1143 
   1144   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
   1145   {
   1146     struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[i];
   1147 
   1148     /* compute request id */
   1149     struct FROSIX_DkgRequestIdP request_id;
   1150     FROSIX_compute_dkg_request_id (
   1151       &request_id,
   1152       &dp->context_string,
   1153       &dp->auth_hash,
   1154       &dp->provider_salt,
   1155       dp->provider_index,
   1156       ds->dkg_data->num_of_participants,
   1157       ds->dkg_data->threshold);
   1158 
   1159     ds->dco[i] = FROSIX_dkg_commitment_request (
   1160       FROSIX_REDUX_ctx_,
   1161       dp->backend_url,
   1162       &request_id,
   1163       dp->provider_index,
   1164       ds->dkg_data->threshold,
   1165       ds->dkg_data->num_of_participants,
   1166       &dp->context_string,
   1167       &dp->auth_hash,
   1168       ds->dkg_data->providers_public_keys,
   1169       &dkg_commitment_request_cb,
   1170       ds);
   1171 
   1172     ds->counter++;
   1173   }
   1174 }
   1175 
   1176 
   1177 /**
   1178  Callback to process a GET /seed request
   1179  *
   1180  * @param cls closure
   1181  * @param ps the decoded response body
   1182 */
   1183 static void
   1184 seed_request_cb (void *cls,
   1185                  unsigned int http_status,
   1186                  const struct FROSIX_ProviderSeed *ps)
   1187 {
   1188   GNUNET_assert (NULL != cls);
   1189   struct FROSIX_DkgState *ds = cls;
   1190 
   1191   if (0 >= ds->counter)
   1192   {
   1193     /* We haven't expected this callback, thus just ignore it */
   1194     return;
   1195   }
   1196 
   1197   /* check if the call was successful */
   1198   if (0 == http_status)
   1199   {
   1200     ds->counter = 0;
   1201 
   1202     // FIXME: cancel all other running and not yet returned requests
   1203     json_t *error_message;
   1204     error_message = GNUNET_JSON_PACK (
   1205       GNUNET_JSON_pack_string ("Frosix_client_error",
   1206                                "Error requesting seed from provider"));
   1207 
   1208     ds->cb (ds->cb_cls,
   1209             0,
   1210             error_message);
   1211 
   1212     return;
   1213   }
   1214 
   1215   /* check if provider index is valid */
   1216   GNUNET_assert (0 < ps->provider_index);
   1217   GNUNET_assert (ds->dkg_data->num_of_participants >= ps->provider_index);
   1218 
   1219   /* copy seed to our main struct */
   1220   struct FROSIX_DkgProvider *dp = &ds->dkg_data->providers[ps->provider_index
   1221                                                            - 1];
   1222 
   1223   memcpy (&dp->seed,
   1224           ps->seed,
   1225           FROSIX_SEED_SIZE);
   1226 
   1227   ds->counter--;
   1228   if (0 == ds->counter)
   1229   {
   1230     GNUNET_free (ds->sgo);
   1231     ds->sgo = NULL;
   1232     /* we are the last, go ahead with dkg-commitment */
   1233     start_dkg_commitments (ds);
   1234   }
   1235 }
   1236 
   1237 
   1238 /**
   1239  * FIXME
   1240 */
   1241 static void
   1242 start_seed_requests (struct FROSIX_DkgState *ds)
   1243 {
   1244   ds->counter = 0;
   1245   ds->sgo = GNUNET_malloc (ds->dkg_data->num_of_participants * sizeof (char *));
   1246 
   1247   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
   1248   {
   1249     ds->sgo[i] = FROSIX_seed_get (FROSIX_REDUX_ctx_,
   1250                                   ds->dkg_data->providers[i].backend_url,
   1251                                   i + 1,
   1252                                   &seed_request_cb,
   1253                                   ds);
   1254     ds->counter++;
   1255   }
   1256 }
   1257 
   1258 
   1259 /**
   1260  * Callback to process a GET /config request
   1261  *
   1262  * @param cls closure
   1263  * @param fcfg the decoded response body
   1264 */
   1265 static void
   1266 config_request_cb (void *cls,
   1267                    unsigned int http_status,
   1268                    const struct FROSIX_Config *fcfg)
   1269 {
   1270   GNUNET_assert (NULL != cls);
   1271   struct FROSIX_DkgState *ds = cls;
   1272 
   1273   if (0 >= ds->counter)
   1274   {
   1275     /* We haven't expected this callback, thus just ignore it */
   1276     return;
   1277   }
   1278 
   1279   /* check if the call was successful */
   1280   if (0 == http_status)
   1281   {
   1282     ds->counter = 0;
   1283 
   1284     // FIXME: cancel all other running and not yet returned requests
   1285     json_t *error_message;
   1286     error_message = GNUNET_JSON_PACK (
   1287       GNUNET_JSON_pack_string ("Frosix_client_error",
   1288                                "Error requesting config from provider"));
   1289 
   1290     ds->cb (ds->cb_cls,
   1291             0,
   1292             error_message);
   1293 
   1294     return;
   1295   }
   1296 
   1297   /* check if provider index is valid */
   1298   GNUNET_assert (0 < fcfg->provider_index);
   1299   GNUNET_assert (ds->dkg_data->num_of_participants >= fcfg->provider_index);
   1300 
   1301   {
   1302     /* copy config data to our main struct */
   1303     struct FROSIX_DkgProvider *dp =
   1304       &ds->dkg_data->providers[fcfg->provider_index - 1];
   1305 
   1306     size_t len = strlen (fcfg->business_name);
   1307     dp->provider_name = strndup (fcfg->business_name,
   1308                                  len);
   1309 
   1310     memcpy (&dp->provider_salt,
   1311             &fcfg->provider_salt,
   1312             sizeof (fcfg->provider_salt));
   1313 
   1314     memcpy (&dp->provider_public_key,
   1315             &fcfg->public_key,
   1316             sizeof (fcfg->public_key));
   1317   }
   1318 
   1319   ds->counter--;
   1320   if (0 == ds->counter)
   1321   {
   1322     GNUNET_free (ds->co);
   1323     ds->co = NULL;
   1324 
   1325     /* we are the last, build array of public keys
   1326     and go ahead with the seeds */
   1327     keygen_build_public_key_array (ds->dkg_data);
   1328 
   1329     start_seed_requests (ds);
   1330   }
   1331 };
   1332 
   1333 
   1334 /**
   1335  * FIXME
   1336 */
   1337 static void
   1338 start_config_requests (struct FROSIX_DkgState *ds)
   1339 {
   1340   ds->counter = 0;
   1341   ds->co = GNUNET_malloc (ds->dkg_data->num_of_participants * sizeof (char *));
   1342 
   1343   for (unsigned int i = 0; i < ds->dkg_data->num_of_participants; i++)
   1344   {
   1345     ds->dkg_data->providers[i].provider_index = i + 1;
   1346     ds->co[i] = FROSIX_get_config (FROSIX_REDUX_ctx_,
   1347                                    ds->dkg_data->providers[i].backend_url,
   1348                                    i + 1,
   1349                                    &config_request_cb,
   1350                                    ds);
   1351     ds->counter++;
   1352   }
   1353 }
   1354 
   1355 
   1356 /**
   1357  * Helper function to parse a keygen input
   1358  *
   1359  * @param[in,out] dkg_data A initialized struct
   1360  * @param[in] arguments Input from the cli
   1361 */
   1362 enum GNUNET_GenericReturnValue
   1363 parse_keygen_arguments (struct FROSIX_DkgData *dkg_data,
   1364                         const json_t *arguments)
   1365 {
   1366   json_t *providers = NULL;
   1367 
   1368   struct GNUNET_JSON_Specification spec[] = {
   1369     GNUNET_JSON_spec_uint8 ("threshold",
   1370                             &dkg_data->threshold),
   1371     GNUNET_JSON_spec_uint64 ("expiration",
   1372                              &dkg_data->expiration),
   1373     GNUNET_JSON_spec_json ("providers",
   1374                            &providers),
   1375     GNUNET_JSON_spec_end ()
   1376   };
   1377 
   1378   if (GNUNET_OK != GNUNET_JSON_parse (arguments,
   1379                                       spec,
   1380                                       NULL,
   1381                                       NULL))
   1382   {
   1383     GNUNET_break (0);
   1384     GNUNET_JSON_parse_free (spec);
   1385     return GNUNET_NO;
   1386   }
   1387 
   1388   /* get number of providers */
   1389   size_t num_of_providers = json_array_size (providers);
   1390 
   1391   /* validate number of providers */
   1392   if (num_of_providers > 254
   1393       || num_of_providers < 2
   1394       || dkg_data->threshold < 1
   1395       || num_of_providers <= dkg_data->threshold)
   1396     return GNUNET_NO;
   1397 
   1398   dkg_data->num_of_participants = num_of_providers;
   1399 
   1400   /* initialize providers */
   1401   dkg_data->providers =  GNUNET_new_array (dkg_data->num_of_participants,
   1402                                            struct FROSIX_DkgProvider);
   1403 
   1404   /* parse provider data */
   1405   for (unsigned int i = 0; i < dkg_data->num_of_participants; i++)
   1406   {
   1407     struct GNUNET_JSON_Specification prov_spec[] = {
   1408       GNUNET_JSON_spec_string ("url",
   1409                                (const
   1410                                 char**) &dkg_data->providers[i].backend_url),
   1411       GNUNET_JSON_spec_fixed_auto ("public_key",
   1412                                    &dkg_data->providers[i].provider_public_key),
   1413       GNUNET_JSON_spec_string ("auth_method",
   1414                                (const
   1415                                 char**) &dkg_data->providers[i].auth_method),
   1416       GNUNET_JSON_spec_string ("auth_data",
   1417                                (const
   1418                                 char**) &dkg_data->providers[i].auth_data),
   1419       GNUNET_JSON_spec_mark_optional (
   1420         GNUNET_JSON_spec_string ("auth_answer",
   1421                                  (const
   1422                                   char**) &dkg_data->providers[i].auth_answer),
   1423         NULL),
   1424       GNUNET_JSON_spec_end ()
   1425     };
   1426 
   1427     if (GNUNET_OK != GNUNET_JSON_parse (json_array_get (providers,
   1428                                                         i),
   1429                                         prov_spec,
   1430                                         NULL,
   1431                                         NULL))
   1432     {
   1433       GNUNET_break (0);
   1434       GNUNET_JSON_parse_free (prov_spec);
   1435       GNUNET_JSON_parse_free (spec);
   1436       return GNUNET_NO;
   1437     }
   1438 
   1439     GNUNET_JSON_parse_free (prov_spec);
   1440   }
   1441 
   1442   GNUNET_JSON_parse_free (spec);
   1443   return GNUNET_OK;
   1444 }
   1445 
   1446 
   1447 struct FROSIX_ReduxAction *
   1448 FROSIX_redux_keygen_start (const json_t *arguments,
   1449                            FROSIX_ActionCallback cb,
   1450                            void *cb_cls)
   1451 {
   1452   /* initialize dkg data struct */
   1453   struct FROSIX_DkgData *dkg_data = GNUNET_new (struct FROSIX_DkgData);
   1454 
   1455   /* parse arguments from cli */
   1456   if (GNUNET_OK != parse_keygen_arguments (dkg_data,
   1457                                            arguments))
   1458   {
   1459     free_dkg_data_struct (dkg_data);
   1460     GNUNET_free (dkg_data);
   1461     json_t *error_message;
   1462     error_message = GNUNET_JSON_PACK (
   1463       GNUNET_JSON_pack_string ("Frosix_client_error",
   1464                                "Error while parsing input"));
   1465 
   1466     cb (cb_cls,
   1467         0,
   1468         error_message);
   1469 
   1470     return NULL;
   1471   }
   1472 
   1473   /* lets create a state */
   1474   struct FROSIX_DkgState *ds = GNUNET_new (struct FROSIX_DkgState);
   1475   ds->cb = cb;
   1476   ds->cb_cls = cb_cls;
   1477   ds->dkg_data = dkg_data;
   1478   ds->ra.cleanup = &keygen_cancel_cb;
   1479   ds->ra.cleanup_cls = ds;
   1480 
   1481   /* get configs from all parsed providers */
   1482   start_config_requests (ds);
   1483 
   1484   return &ds->ra;
   1485 }