frosix

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

frosix_api_sign.c (20473B)


      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_sign_redux.c
     18  * @brief frosix reducer sign 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 "frost_verify.h"
     27 #include "frosix.h"
     28 #include "frosix_api.h"
     29 #include <taler/taler_merchant_service.h>
     30 
     31 
     32 /**
     33  * FIXME
     34 */
     35 struct FROSIX_Provider
     36 {
     37   /**
     38    * URL of the provider.
     39   */
     40   char *backend_url;
     41 
     42   /**
     43    * Index of the provider
     44   */
     45   uint8_t provider_index;
     46 
     47   /**
     48    * Authentication data.
     49   */
     50   struct GNUNET_HashCode auth_data;
     51 
     52   /**
     53    *
     54   */
     55   struct GNUNET_CRYPTO_Edx25519PublicKey auth_pub;
     56 
     57   /**
     58    *
     59   */
     60   struct GNUNET_CRYPTO_Edx25519Signature auth_sig;
     61 
     62   /**
     63    *
     64   */
     65   const char *auth_method;
     66 
     67   /**
     68    * Encryption key
     69   */
     70   struct FROSIX_EncryptionKey enc_key;
     71 
     72   /**
     73    * Commitment for this signature process.
     74   */
     75   struct FROST_Commitment commitment;
     76 
     77   /**
     78    * The resulting signature share of this provider.
     79   */
     80   struct FROST_SignatureShare sig_share;
     81 };
     82 
     83 /**
     84  * Struct to store all parsed data from the cli and /config and /seed
     85 */
     86 struct FROSIX_SignatureData
     87 {
     88   /**
     89    * What is the threshold value?
     90   */
     91   uint8_t threshold;
     92 
     93   /**
     94    * Public key to verify the resulting signature
     95   */
     96   struct FROST_PublicKey public_key;
     97 
     98   /**
     99    * Our hashed message.
    100   */
    101   struct FROST_MessageHash message_hash;
    102 
    103   /**
    104    * Pointer to a list of providers, length is @e threshold
    105   */
    106   struct FROSIX_Provider *providers;
    107 
    108   /**
    109    * Resulting signature
    110   */
    111   struct FROST_Signature signature;
    112 };
    113 
    114 /**
    115  * State of a sign procedure
    116 */
    117 struct FROSIX_SignatureState
    118 {
    119   /**
    120    * State we are updating.
    121    */
    122   struct FROSIX_SignatureData *sig_data;
    123 
    124   /**
    125    * Function to call when we are done.
    126    */
    127   FROSIX_ActionCallback cb;
    128 
    129   /**
    130    * Closure for @e cb.
    131    */
    132   void *cb_cls;
    133 
    134   /**
    135    * Redux action we returned to our controller.
    136    */
    137   struct FROSIX_ReduxAction ra;
    138 
    139   /**
    140    * Number of provider /config operations in @e ba_head that
    141    * are still awaiting completion.
    142    */
    143   uint8_t counter;
    144 
    145   /**
    146    * Last error code
    147   */
    148   enum TALER_ErrorCode error_code;
    149 
    150   /**
    151     * Array of config requests, with length `num_of_participants`
    152   */
    153   struct FROSIX_ConfigOperation **co;
    154 
    155   /**
    156    * Array of signature commitment requests with length @e threshold.
    157   */
    158   struct FROSIX_SigCommitmentRequestOperation **sco;
    159 
    160   /**
    161    * Array of signature share requests with length @e threshold.
    162   */
    163   struct FROSIX_SigShareRequestOperation **sso;
    164 
    165 };
    166 
    167 
    168 /**
    169  * Function to free all initialized memory of a provider from a
    170  * `struct FROSIX_Provider`
    171  *
    172  * @param fp the struct to clean up
    173 */
    174 static void
    175 free_provider_struct (struct FROSIX_Provider *fp)
    176 {
    177   if (NULL != fp->backend_url)
    178     GNUNET_free (fp->backend_url);
    179 }
    180 
    181 
    182 /**
    183  * Function to free all initialized memory of a provider from a
    184  * `struct FROSIX_SignatureData`
    185  *
    186  * @param dd the struct to clean up
    187 */
    188 static void
    189 free_signature_data_struct (struct FROSIX_SignatureData *sd)
    190 {
    191   if (NULL != sd->providers)
    192   {
    193     for (unsigned int i = 0; i < sd->threshold; i++)
    194     {
    195       if (NULL != &sd->providers[i])
    196         free_provider_struct (&sd->providers[i]);
    197     }
    198 
    199     GNUNET_free (sd->providers);
    200   }
    201 }
    202 
    203 
    204 /**
    205  * Function called when signature process is being aborted.
    206  * Frees all initialized memory!
    207  *
    208  * @param cls a `struct FROSIX_SignatureState`
    209 */
    210 static void
    211 sign_cancel_cb (void *cls)
    212 {
    213   struct FROSIX_SignatureState *ss = cls;
    214 
    215   if (NULL != ss->sig_data)
    216   {
    217     free_signature_data_struct (ss->sig_data);
    218     GNUNET_free (ss->sig_data);
    219   }
    220 
    221 
    222   /* free operations */
    223   if (NULL != ss->co)
    224     GNUNET_free (ss->co);
    225 
    226   if (NULL != ss->sco)
    227     GNUNET_free (ss->sco);
    228 
    229   if (NULL != ss->sso)
    230     GNUNET_free (ss->sso);
    231 
    232   GNUNET_free (ss);
    233 
    234 }
    235 
    236 
    237 /**
    238  * FIXME
    239 */
    240 static void
    241 check_and_prepare_signature (const struct FROSIX_SignatureState *ss)
    242 {
    243   /* build array of commitments - needed for verification */
    244   struct FROST_Commitment commitments[ss->sig_data->threshold];
    245   for (unsigned int i = 0; i < ss->sig_data->threshold; i++)
    246   {
    247     struct FROSIX_Provider *fp = &ss->sig_data->providers[i];
    248 
    249     commitments[i].identifier = fp->commitment.identifier;
    250 
    251     memcpy (&commitments[i].hiding_commitment,
    252             &fp->commitment.hiding_commitment,
    253             sizeof (fp->commitment.hiding_commitment));
    254 
    255     memcpy (&commitments[i].binding_commitment,
    256             &fp->commitment.binding_commitment,
    257             sizeof (fp->commitment.binding_commitment));
    258   }
    259 
    260   /* verify received signature share */
    261   for (unsigned int i = 0; i < ss->sig_data->threshold; i++)
    262   {
    263     struct FROSIX_Provider *fp = &ss->sig_data->providers[i];
    264 
    265     GNUNET_assert (FROST_verify_signature_share (
    266                      &fp->commitment,
    267                      &fp->sig_share,
    268                      commitments,
    269                      ss->sig_data->threshold,
    270                      &ss->sig_data->public_key,
    271                      &ss->sig_data->message_hash));
    272   }
    273 
    274   /* copy all signature shares together */
    275   struct FROST_SignatureShare sig_shares[ss->sig_data->threshold];
    276   for (unsigned int i = 0; i < ss->sig_data->threshold; i++)
    277   {
    278     struct FROSIX_Provider *fp = &ss->sig_data->providers[i];
    279 
    280     sig_shares[i].identifier = fp->sig_share.identifier;
    281 
    282     memcpy (&sig_shares[i].sig_share,
    283             &fp->sig_share.sig_share,
    284             sizeof (fp->sig_share.sig_share));
    285 
    286     memcpy (&sig_shares[i].pk_i,
    287             &fp->sig_share.pk_i,
    288             sizeof (fp->sig_share.pk_i));
    289   }
    290 
    291   /* build signature */
    292   FROST_compose_signature (&ss->sig_data->signature,
    293                            commitments,
    294                            sig_shares,
    295                            ss->sig_data->threshold,
    296                            &ss->sig_data->message_hash);
    297 
    298   /* verify signature */
    299   GNUNET_assert (FROST_verify_signature (&ss->sig_data->public_key,
    300                                          &ss->sig_data->signature,
    301                                          &ss->sig_data->message_hash));
    302 
    303   /* build json */
    304   json_t *result;
    305 
    306   result = GNUNET_JSON_PACK (
    307     GNUNET_JSON_pack_data_auto ("message_hash",
    308                                 &ss->sig_data->message_hash),
    309     GNUNET_JSON_pack_data_auto ("public_key",
    310                                 &ss->sig_data->public_key),
    311     GNUNET_JSON_pack_data_auto ("signature_r",
    312                                 &ss->sig_data->signature.r),
    313     GNUNET_JSON_pack_data_auto ("signature_z",
    314                                 &ss->sig_data->signature.z)
    315     );
    316 
    317   /* free all initialized data */
    318   free_signature_data_struct (ss->sig_data);
    319 
    320   ss->cb (ss->cb_cls,
    321           ss->error_code,
    322           result);
    323 }
    324 
    325 
    326 /**
    327  * Callback to process a POST /sig-share request
    328  *
    329  * @param cls closure
    330  * @param ssd the decoded response body
    331 */
    332 static void
    333 signature_share_request_cb (void *cls,
    334                             const struct FROSIX_SigShareRequestDetails *ssd)
    335 {
    336   GNUNET_assert (NULL != cls);
    337   struct FROSIX_SignatureState *ss = cls;
    338 
    339   /* set error code */
    340   ss->error_code = ssd->ec;
    341 
    342   /* check if this is a valid callback */
    343   GNUNET_assert (0 < ss->counter);
    344   GNUNET_assert (0 != ssd->http_status);
    345 
    346   /* check if provider index is valid */
    347   GNUNET_assert (0 < ssd->sig_share.identifier);
    348   GNUNET_assert (255 > ssd->sig_share.identifier);
    349 
    350   struct FROSIX_Provider *fp = &ss->sig_data->providers[ssd->array_index];
    351 
    352   /* Fill return values in our central struct */
    353   fp->sig_share.identifier = ssd->sig_share.identifier;
    354 
    355   memcpy (&fp->sig_share.sig_share,
    356           &ssd->sig_share.sig_share,
    357           sizeof (ssd->sig_share.sig_share));
    358 
    359   memcpy (&fp->sig_share.pk_i,
    360           &ssd->sig_share.pk_i,
    361           sizeof (ssd->sig_share.pk_i));
    362 
    363   /* call next dkg-commitment request */
    364   ss->counter--;
    365   if (0 == ss->counter)
    366   {
    367     /* we are the last, check received shares and build final signature */
    368     check_and_prepare_signature (ss);
    369   }
    370 }
    371 
    372 
    373 /**
    374  * FIXME
    375 */
    376 static void
    377 start_signature_shares (struct FROSIX_SignatureState *ss)
    378 {
    379   ss->sso = GNUNET_malloc (ss->sig_data->threshold * sizeof (char *));
    380   ss->counter = 0;
    381 
    382   /* build commitment array */
    383   struct FROST_Commitment commitments[ss->sig_data->threshold];
    384   for (unsigned int i = 0; i < ss->sig_data->threshold; i++)
    385   {
    386     struct FROSIX_Provider *fp = &ss->sig_data->providers[i];
    387 
    388     commitments[i].identifier = fp->commitment.identifier;
    389 
    390     FROST_point_copy_to (&commitments[i].hiding_commitment,
    391                          &fp->commitment.hiding_commitment);
    392 
    393     FROST_point_copy_to (&commitments[i].binding_commitment,
    394                          &fp->commitment.binding_commitment);
    395   }
    396 
    397   for (unsigned int i = 0; i < ss->sig_data->threshold; i++)
    398   {
    399     struct FROSIX_Provider *fp = &ss->sig_data->providers[i];
    400 
    401     /* hash encryption key */
    402     struct FROST_HashCode enc_key_hash;
    403     FROSIX_hash_encryption_key (&enc_key_hash,
    404                                 &fp->enc_key);
    405 
    406     /* compute request id */
    407     struct FROSIX_SigRequestIdP request_id;
    408     FROSIX_compute_signature_request_id (
    409       &request_id,
    410       &enc_key_hash,
    411       &ss->sig_data->message_hash);
    412 
    413     ss->sso[i] = FROSIX_sig_share_request (
    414       FROSIX_REDUX_ctx_,
    415       fp->backend_url,
    416       &request_id,
    417       fp->provider_index,
    418       i,
    419       &fp->enc_key,
    420       &ss->sig_data->message_hash,
    421       commitments,
    422       ss->sig_data->threshold,
    423       &signature_share_request_cb,
    424       ss);
    425 
    426     ss->counter++;
    427   }
    428 }
    429 
    430 
    431 
    432 /**
    433  * Callback to process a POST /sig-commitment request
    434  *
    435  * @param cls closure
    436  * @param scd the decoded response body
    437 */
    438 static void
    439 signature_commitment_request_cb (void *cls,
    440                                  const struct
    441                                  FROSIX_SigCommitmentRequestDetails *scd)
    442 {
    443   GNUNET_assert (NULL != cls);
    444   struct FROSIX_SignatureState *ss = cls;
    445 
    446   /* set error code */
    447   ss->error_code = scd->ec;
    448 
    449   /* check if we have to abort the signing process */
    450   if (0 == scd->http_status)
    451   {
    452     ss->cb (ss,
    453             ss->error_code,
    454             NULL);
    455     return;
    456   }
    457 
    458 
    459   /* check if this is a valid callback */
    460   GNUNET_assert (0 < ss->counter);
    461 
    462   /* check if provider index is valid */
    463   GNUNET_assert (0 < scd->sig_commitment.identifier);
    464   GNUNET_assert (255 > scd->sig_commitment.identifier);
    465 
    466   /* copy commitment in our struct */
    467   struct FROSIX_Provider *fp = &ss->sig_data->providers[scd->array_index];
    468 
    469   /* Fill return values in our central struct */
    470   fp->commitment.identifier = scd->sig_commitment.identifier;
    471 
    472   FROST_point_copy_to (&fp->commitment.hiding_commitment,
    473                        &scd->sig_commitment.hiding_commitment);
    474 
    475   FROST_point_copy_to (&fp->commitment.binding_commitment,
    476                        &scd->sig_commitment.binding_commitment);
    477 
    478   /* call next dkg-commitment request */
    479   ss->counter--;
    480   if (0 == ss->counter)
    481   {
    482     /* we are the last, go ahead with sig-share */
    483     start_signature_shares (ss);
    484   }
    485 }
    486 
    487 
    488 /**
    489  * FIXME
    490 */
    491 static void
    492 start_signature_commitments (struct FROSIX_SignatureState *ss)
    493 {
    494   ss->sco = GNUNET_malloc (ss->sig_data->threshold * sizeof (char *));
    495   ss->counter = 0;
    496   for (unsigned int i = 0; i < ss->sig_data->threshold; i++)
    497   {
    498     struct FROSIX_Provider *fp = &ss->sig_data->providers[i];
    499 
    500     /* hash encryption key */
    501     struct FROST_HashCode enc_key_hash;
    502     FROSIX_hash_encryption_key (&enc_key_hash,
    503                                 &fp->enc_key);
    504 
    505     /* compute request id */
    506     struct FROSIX_SigRequestIdP request_id;
    507     FROSIX_compute_signature_request_id (
    508       &request_id,
    509       &enc_key_hash,
    510       &ss->sig_data->message_hash);
    511 
    512     if (0 == strcmp (fp->auth_method,
    513                      "question"))
    514     {
    515       ss->sco[i] = FROSIX_sig_commitment_request (
    516         FROSIX_REDUX_ctx_,
    517         fp->backend_url,
    518         &request_id,
    519         fp->provider_index,
    520         i,
    521         &enc_key_hash,
    522         NULL,
    523         &fp->auth_pub,
    524         &fp->auth_sig,
    525         fp->auth_method,
    526         &ss->sig_data->message_hash,
    527         &signature_commitment_request_cb,
    528         ss);
    529     }
    530     else
    531     {
    532       ss->sco[i] = FROSIX_sig_commitment_request (
    533         FROSIX_REDUX_ctx_,
    534         fp->backend_url,
    535         &request_id,
    536         fp->provider_index,
    537         i,
    538         &enc_key_hash,
    539         &fp->auth_data,
    540         NULL,
    541         NULL,
    542         fp->auth_method,
    543         &ss->sig_data->message_hash,
    544         &signature_commitment_request_cb,
    545         ss);
    546     }
    547 
    548 
    549     ss->counter++;
    550   }
    551 }
    552 
    553 
    554 /**
    555  * Helper function to parse a keygen input
    556  *
    557  * @param[in,out] dkg_data A initialized struct
    558  * @param[in] arguments Input from the cli
    559 */
    560 enum GNUNET_GenericReturnValue
    561 parse_sign_arguments (struct FROSIX_SignatureData *sig_data,
    562                       const json_t *arguments,
    563                       json_t *input)
    564 {
    565   json_t *providers = NULL;
    566   uint8_t max_num = 0;
    567 
    568   struct GNUNET_JSON_Specification spec[] = {
    569     GNUNET_JSON_spec_uint8 ("number_of_participants",
    570                             &max_num),
    571     GNUNET_JSON_spec_uint8 ("threshold",
    572                             &sig_data->threshold),
    573     GNUNET_JSON_spec_fixed_auto ("public_key",
    574                                  &sig_data->public_key),
    575     GNUNET_JSON_spec_json ("providers",
    576                            &providers),
    577     GNUNET_JSON_spec_end ()
    578   };
    579 
    580   if (GNUNET_OK != GNUNET_JSON_parse (arguments,
    581                                       spec,
    582                                       NULL,
    583                                       NULL))
    584   {
    585     GNUNET_break (0);
    586     GNUNET_JSON_parse_free (spec);
    587     return GNUNET_NO;
    588   }
    589 
    590   /* get number of providers */
    591   size_t num_of_providers = json_object_size (input);
    592 
    593   /* validate number of providers */
    594   GNUNET_assert (sig_data->threshold == num_of_providers);
    595   GNUNET_assert (254 > sig_data->threshold);
    596   GNUNET_assert (0 < sig_data->threshold);
    597 
    598   /* initialize providers */
    599   sig_data->providers =  GNUNET_new_array (sig_data->threshold,
    600                                            struct FROSIX_Provider);
    601 
    602   uint8_t provider_mapping[sig_data->threshold];
    603 
    604   /* get involved providers */
    605   const char *key;
    606   json_t *value;
    607   unsigned int counter = 0;
    608   json_object_foreach (input,
    609                        key,
    610                        value)
    611   {
    612     /* try to convert key value (string) to unsigned int */
    613     int key_as_int = atoi (key);
    614 
    615     GNUNET_assert (0 < key_as_int);
    616     GNUNET_assert (254 > key_as_int);
    617     GNUNET_assert (max_num >= key_as_int);
    618 
    619     provider_mapping[counter] = (uint8_t) key_as_int;
    620     counter++;
    621   }
    622 
    623   /* parse provider data */
    624   for (unsigned int i = 0; i < sig_data->threshold; i++)
    625   {
    626     struct GNUNET_HashCode auth_nonce;
    627     uint8_t provider_index = provider_mapping[i];
    628     struct GNUNET_JSON_Specification prov_spec[] = {
    629       GNUNET_JSON_spec_uint8 ("provider_index",
    630                               &sig_data->providers[i].provider_index),
    631       GNUNET_JSON_spec_string ("backend_url",
    632                                (const
    633                                 char**) &sig_data->providers[i].backend_url),
    634       GNUNET_JSON_spec_fixed_auto ("encryption_key",
    635                                    &sig_data->providers[i].enc_key),
    636       GNUNET_JSON_spec_string ("auth_method",
    637                                &sig_data->providers[i].auth_method),
    638       GNUNET_JSON_spec_fixed_auto ("auth_nonce",
    639                                    &auth_nonce),
    640       GNUNET_JSON_spec_end ()
    641     };
    642 
    643     if (GNUNET_OK != GNUNET_JSON_parse (json_array_get (providers,
    644                                                         provider_index - 1),
    645                                         prov_spec,
    646                                         NULL,
    647                                         NULL))
    648     {
    649       GNUNET_break (0);
    650       GNUNET_JSON_parse_free (prov_spec);
    651       GNUNET_JSON_parse_free (spec);
    652       return GNUNET_NO;
    653     }
    654 
    655     GNUNET_JSON_parse_free (prov_spec);
    656 
    657     /* convert int index to a string - this is our key */
    658     char index[5];
    659     snprintf (index,
    660               4,
    661               "%d",
    662               sig_data->providers[i].provider_index);
    663 
    664     /* parse challenge solution / answer of security question */
    665     if (0 == strcmp (sig_data->providers[i].auth_method,
    666                      "question"))
    667     {
    668       const char *answer;
    669 
    670       struct GNUNET_JSON_Specification q_spec[] = {
    671         GNUNET_JSON_spec_string (index,
    672                                  &answer),
    673         GNUNET_JSON_spec_end ()
    674       };
    675 
    676       if (GNUNET_OK != GNUNET_JSON_parse (input,
    677                                           q_spec,
    678                                           NULL,
    679                                           NULL))
    680       {
    681         GNUNET_break (0);
    682         GNUNET_JSON_parse_free (q_spec);
    683         return GNUNET_NO;
    684       }
    685 
    686       GNUNET_JSON_parse_free (q_spec);
    687 
    688       unsigned int amplifier = 1;
    689       /* compute key pair to sign signature */
    690       struct GNUNET_CRYPTO_Edx25519PrivateKey priv;
    691       struct FROSIX_ChallengeHashP auth_hash;
    692       FROSIX_hash_pow (&auth_hash.hash,
    693                        &priv,
    694                        &sig_data->providers[i].auth_pub,
    695                        &auth_nonce,
    696                        answer,
    697                        amplifier);
    698 
    699       // Sign data
    700       struct FROSIX_AuthSignaturePS as = {
    701         .purpose.purpose = htonl (72),
    702         .purpose.size = htonl (sizeof (as)),
    703         .mh = sig_data->message_hash,
    704       };
    705 
    706       GNUNET_CRYPTO_edx25519_sign (&priv,
    707                                    &as,
    708                                    &sig_data->providers[i].auth_sig);
    709     }
    710     else
    711     {
    712       /* parse answer as number */
    713       uint64_t code;
    714 
    715       struct GNUNET_JSON_Specification c_spec[] = {
    716         GNUNET_JSON_spec_uint64 (index,
    717                                  &code),
    718         GNUNET_JSON_spec_end ()
    719       };
    720 
    721       if (GNUNET_OK != GNUNET_JSON_parse (input,
    722                                           c_spec,
    723                                           NULL,
    724                                           NULL))
    725       {
    726         GNUNET_break (0);
    727         GNUNET_JSON_parse_free (c_spec);
    728         return GNUNET_NO;
    729       }
    730 
    731       GNUNET_JSON_parse_free (c_spec);
    732 
    733       /* compute challenge hash */
    734       FROSIX_hash_answer (code,
    735                           &sig_data->providers[i].auth_data);
    736     }
    737   }
    738 
    739   GNUNET_JSON_parse_free (spec);
    740 
    741   /* check if list of providers is sorted */
    742   for (unsigned int i = 1; i < sig_data->threshold; i++)
    743   {
    744     GNUNET_assert (sig_data->providers[i].provider_index >
    745                    sig_data->providers[i - 1].provider_index);
    746   }
    747 
    748   return GNUNET_OK;
    749 }
    750 
    751 
    752 /**
    753  *
    754 */
    755 struct FROSIX_ReduxAction *
    756 FROSIX_redux_sign_start (const json_t *arguments,
    757                          json_t *input,
    758                          const char *message,
    759                          FROSIX_ActionCallback cb,
    760                          void *cb_cls)
    761 {
    762   /* initialize signature data struct */
    763   struct FROSIX_SignatureData *sig_data = GNUNET_new (struct
    764                                                       FROSIX_SignatureData);
    765 
    766   /* hash message */
    767   FROST_message_to_hash (&sig_data->message_hash,
    768                          message,
    769                          strlen (message));
    770 
    771   /* parse arguments from cli */
    772   if (GNUNET_OK != parse_sign_arguments (sig_data,
    773                                          arguments,
    774                                          input))
    775   {
    776     free_signature_data_struct (sig_data);
    777 
    778     // FIXME: Return some useful error message
    779     return NULL;
    780   }
    781 
    782   /* lets create a state */
    783   struct FROSIX_SignatureState *ss = GNUNET_new (struct FROSIX_SignatureState);
    784   ss->cb = cb;
    785   ss->cb_cls = cb_cls;
    786   ss->sig_data = sig_data;
    787   ss->ra.cleanup = &sign_cancel_cb;
    788   ss->ra.cleanup_cls = ss;
    789 
    790   /* get commitments from all parsed providers */
    791   start_signature_commitments (ss);
    792 
    793   return &ss->ra;
    794 }