frosix

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

frosix-httpd_dkg-shares.c (21996B)


      1 /*
      2   This file is part of Frosix
      3   Copyright (C) 2022, 2023 Joel Urech
      4 
      5   Frosix is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3, or (at your option) any later version.
      8 
      9   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 Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   Frosix; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @file backend/frosix-httpd_dkg-shares.c
     18  * @brief functions to handle incoming requests on /dkg-shares
     19  * @author Joel Urech
     20  */
     21 #include "frosix-httpd_dkg.h"
     22 #include "frosix-httpd.h"
     23 #include "frosix_database_plugin.h"
     24 #include "frosix_service.h"
     25 #include "keygen.h"
     26 #include <taler/taler_util.h>
     27 #include <gnunet/gnunet_util_lib.h>
     28 #include <gnunet/gnunet_db_lib.h>
     29 
     30 struct DkgSharesContext
     31 {
     32   /**
     33    *
     34   */
     35   uint8_t provider_index;
     36 
     37   /**
     38    *
     39   */
     40   uint8_t threshold;
     41 
     42   /**
     43    *
     44   */
     45   uint8_t num_of_participants;
     46 
     47   /**
     48    *
     49   */
     50   struct FROSIX_DkgContextStringP context_string;
     51 
     52   /**
     53    *
     54   */
     55   struct FROSIX_ChallengeHashP auth_hash;
     56 
     57   /**
     58    *
     59   */
     60   struct FROSIX_DkgRequestIdP request_id;
     61 
     62   /**
     63    *
     64   */
     65   struct FROSIX_ProviderSaltP provider_salt;
     66 
     67   /**
     68    *
     69   */
     70   struct FROSIX_SecretProviderSaltP secret_provider_salt;
     71 
     72   /**
     73    *
     74   */
     75   struct FROST_DkgCommitment *dkg_commitments;
     76 
     77   /**
     78    * Our handler context
     79   */
     80   struct TM_HandlerContext *hc;
     81 
     82   /**
     83    * Uploaded JSON data, NULL if upload is not yet complete.
     84   */
     85   json_t *json;
     86 
     87   /**
     88    * Post parser context.
     89    */
     90   void *post_ctx;
     91 
     92   /**
     93    * Connection handle for closing or resuming
     94    */
     95   struct MHD_Connection *connection;
     96 
     97   /**
     98    * When should this request time out?
     99   */
    100   struct GNUNET_TIME_Absolute timeout;
    101 };
    102 
    103 /**
    104  * Return the generated dkg shares
    105  *
    106  * @param connection
    107  * @param dkg_shares
    108  * @return
    109 */
    110 static MHD_RESULT
    111 return_dkg_shares (
    112   struct MHD_Connection *connection,
    113   const struct FROST_DkgShare dkg_shares[],
    114   const struct GNUNET_CRYPTO_EddsaPublicKey pub_keys[],
    115   uint8_t provider_index,
    116   uint8_t num_of_participants)
    117 {
    118   // Prepare secret shares
    119   json_t *shares;
    120   shares = json_array ();
    121   GNUNET_assert (NULL != shares);
    122   int counter = 0;
    123 
    124   for (int i = 0; i < num_of_participants; i++)
    125   {
    126     if (provider_index - 1 != i)
    127     {
    128       uint8_t target = i + 1;
    129       json_t *share;
    130       share = json_object ();
    131 
    132       /* get key material */
    133       struct GNUNET_CRYPTO_EcdhePrivateKey priv_enc_key;
    134       GNUNET_CRYPTO_ecdhe_key_create (&priv_enc_key);
    135 
    136       struct GNUNET_CRYPTO_EcdhePublicKey pub_enc_key;
    137       GNUNET_CRYPTO_ecdhe_key_get_public (&priv_enc_key,
    138                                           &pub_enc_key);
    139 
    140       struct GNUNET_HashCode key_material;
    141       if (GNUNET_OK != GNUNET_CRYPTO_ecdh_eddsa (&priv_enc_key,
    142                                                  &pub_keys[counter],
    143                                                  &key_material))
    144       {
    145         GNUNET_break (0);
    146         return MHD_NO;
    147       }
    148 
    149       /* derive key */
    150       struct GNUNET_CRYPTO_SymmetricSessionKey sym_key;
    151       struct GNUNET_CRYPTO_SymmetricInitializationVector iv;
    152       GNUNET_CRYPTO_hash_to_aes_key (&key_material,
    153                                      &sym_key,
    154                                      &iv);
    155 
    156       /* encrypt share */
    157       struct FROSIX_EncryptedShareP encrypted_share;
    158       ssize_t len = GNUNET_CRYPTO_symmetric_encrypt (&dkg_shares[i].share,
    159                                                      sizeof (dkg_shares[i].share),
    160                                                      &sym_key,
    161                                                      &iv,
    162                                                      &encrypted_share);
    163 
    164       if (-1 == len || sizeof (encrypted_share) != len)
    165       {
    166         GNUNET_break (0);
    167         return MHD_NO;
    168       }
    169 
    170       /* pack data in json */
    171       share = GNUNET_JSON_PACK (
    172         GNUNET_JSON_pack_uint64 ("target",
    173                                  target),
    174         GNUNET_JSON_pack_uint64 ("issuer",
    175                                  provider_index),
    176         GNUNET_JSON_pack_data_auto ("secret_share",
    177                                     &encrypted_share),
    178         GNUNET_JSON_pack_data_auto ("ephemeral_key",
    179                                     &pub_enc_key)
    180         );
    181 
    182       GNUNET_assert (0 ==
    183                      json_array_append (
    184                        shares,
    185                        share));
    186       counter++;
    187     }
    188   }
    189 
    190   return TALER_MHD_REPLY_JSON_PACK (
    191     connection,
    192     MHD_HTTP_OK,
    193     GNUNET_JSON_pack_array_steal ("secret_shares",
    194                                   shares));
    195 }
    196 
    197 static MHD_RESULT
    198 store_commitments (struct DkgSharesContext *dc)
    199 {
    200   /* copy commitments to a single byte array */
    201   struct FROSIX_DkgCommitmentsRaw commits;
    202   commits.length = (sizeof (dc->provider_index)
    203                     + (sizeof (struct FROST_Point)
    204                        * dc->threshold))
    205                    * (dc->num_of_participants - 1);
    206   commits.ptr_commits = calloc (1, commits.length);
    207 
    208   unsigned int offset = 0;
    209 
    210   for (int i = 0; i < dc->num_of_participants - 1; i++)
    211   {
    212     memcpy ((char *) commits.ptr_commits + offset,
    213             &dc->dkg_commitments[i].identifier,
    214             1);
    215     offset += 1;
    216 
    217     for (int j = 0; j < dc->threshold; j++)
    218     {
    219       memcpy ((char *) commits.ptr_commits + offset,
    220               &dc->dkg_commitments[i].share_comm[j].sc.xcoord,
    221               sizeof (struct FROST_Point));
    222       offset += sizeof (struct FROST_Point);
    223     }
    224   }
    225 
    226   /* store commitments */
    227   enum GNUNET_DB_QueryStatus qs;
    228   qs = db->store_dkg_commitment (db->cls,
    229                                  &dc->request_id,
    230                                  &commits);
    231   switch (qs)
    232   {
    233   case GNUNET_DB_STATUS_HARD_ERROR:
    234   case GNUNET_DB_STATUS_SOFT_ERROR:
    235   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
    236     GNUNET_break (0);
    237     free (commits.ptr_commits);
    238     return TALER_MHD_reply_with_error (dc->connection,
    239                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    240                                        TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
    241                                        "store dkg-commitment");
    242   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
    243     break;
    244   }
    245 
    246   /* free initialized memory */
    247   free (commits.ptr_commits);
    248   return MHD_HTTP_OK;
    249 }
    250 
    251 
    252 MHD_RESULT
    253 FH_handler_dkg_shares_post (
    254   struct MHD_Connection *connection,
    255   struct TM_HandlerContext *hc,
    256   const struct FROSIX_DkgRequestIdP *dkg_id,
    257   const struct FROSIX_ProviderSaltP *provider_salt,
    258   const struct FROSIX_SecretProviderSaltP *secret_provider_salt,
    259   const char *dkg_commitment_data,
    260   size_t *dkg_commitment_data_size)
    261 {
    262   enum GNUNET_GenericReturnValue res;
    263   struct DkgSharesContext *dc = hc->ctx;
    264   json_t *json_ppk = NULL;
    265   json_t *commitments = NULL;
    266 
    267   if (NULL == dc)
    268   {
    269     dc = GNUNET_new (struct DkgSharesContext);
    270     dc->connection = connection;
    271     dc->request_id = *dkg_id;
    272     dc->provider_salt = *provider_salt;
    273     dc->secret_provider_salt = *secret_provider_salt;
    274     hc->ctx = dc;
    275   }
    276 
    277   /* parse request body */
    278   if (NULL == dc->json)
    279   {
    280     res = TALER_MHD_parse_post_json (dc->connection,
    281                                      &dc->post_ctx,
    282                                      dkg_commitment_data,
    283                                      dkg_commitment_data_size,
    284                                      &dc->json);
    285     if (GNUNET_SYSERR == res)
    286     {
    287       GNUNET_break (0);
    288       return MHD_NO;
    289     }
    290     if ((GNUNET_NO == res ||
    291          (NULL == dc->json)))
    292     {
    293       return MHD_YES;
    294     }
    295   }
    296 
    297   struct GNUNET_JSON_Specification spec[] = {
    298     GNUNET_JSON_spec_uint8 ("provider_index",
    299                             &dc->provider_index),
    300     GNUNET_JSON_spec_uint8 ("threshold",
    301                             &dc->threshold),
    302     GNUNET_JSON_spec_fixed_auto ("context_string",
    303                                  &dc->context_string),
    304     GNUNET_JSON_spec_fixed_auto ("auth_hash",
    305                                  &dc->auth_hash),
    306     GNUNET_JSON_spec_json ("providers_public_keys",
    307                            &json_ppk),
    308     GNUNET_JSON_spec_json ("dkg_commitments",
    309                            &commitments),
    310     GNUNET_JSON_spec_end ()
    311   };
    312 
    313   res = TALER_MHD_parse_json_data (connection,
    314                                    dc->json,
    315                                    spec);
    316 
    317   if (GNUNET_SYSERR == res)
    318   {
    319     GNUNET_JSON_parse_free (spec);
    320     GNUNET_break (0);
    321     return MHD_NO;
    322   }
    323   if (GNUNET_NO == res)
    324   {
    325     GNUNET_JSON_parse_free (spec);
    326     GNUNET_break_op (0);
    327     return TALER_MHD_reply_with_error (connection,
    328                                        MHD_HTTP_BAD_REQUEST,
    329                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
    330                                        "Unable to parse request body");
    331   }
    332 
    333   /* check number of submitted provider public keys*/
    334   if (254 < json_array_size (json_ppk))
    335   {
    336     GNUNET_JSON_parse_free (spec);
    337     GNUNET_break_op (0);
    338     return TALER_MHD_reply_with_error (connection,
    339                                        MHD_HTTP_BAD_REQUEST,
    340                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
    341                                        "Too many provider public keys");
    342   }
    343 
    344   /* set number of participants */
    345   dc->num_of_participants = json_array_size (json_ppk);
    346 
    347   /* validate provider index, threshold and num_of_participants */
    348   if (GNUNET_OK != FROST_validate_dkg_params (dc->provider_index,
    349                                               dc->threshold,
    350                                               dc->num_of_participants))
    351   {
    352     GNUNET_JSON_parse_free (spec);
    353     GNUNET_break_op (0);
    354     return TALER_MHD_reply_with_error (connection,
    355                                        MHD_HTTP_BAD_REQUEST,
    356                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
    357                                        "Protocol parameters out of bound");
    358   }
    359 
    360   /* Check if called id is matching the send data */
    361   if (GNUNET_OK != FROSIX_dkg_validate_request_id_ (&dc->request_id,
    362                                                     &dc->context_string,
    363                                                     &dc->auth_hash,
    364                                                     &dc->provider_salt,
    365                                                     dc->provider_index,
    366                                                     dc->num_of_participants,
    367                                                     dc->threshold))
    368   {
    369     GNUNET_JSON_parse_free (spec);
    370     GNUNET_break_op (0);
    371     return TALER_MHD_reply_with_error (connection,
    372                                        MHD_HTTP_BAD_REQUEST,
    373                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
    374                                        "Unable to validate request ID");
    375   }
    376 
    377   /* parse provider public keys */
    378   struct GNUNET_CRYPTO_EddsaPublicKey
    379     providers_public_keys[dc->num_of_participants];
    380   for (unsigned int i = 0; i < dc->num_of_participants; i++)
    381   {
    382     struct GNUNET_JSON_Specification ppk_spec[] = {
    383       GNUNET_JSON_spec_fixed_auto (NULL,
    384                                    &providers_public_keys[i]),
    385       GNUNET_JSON_spec_end ()
    386     };
    387 
    388     res = TALER_MHD_parse_json_array (connection,
    389                                       json_ppk,
    390                                       ppk_spec,
    391                                       i,
    392                                       -1);
    393 
    394     if (GNUNET_SYSERR == res)
    395     {
    396       GNUNET_JSON_parse_free (spec);
    397       GNUNET_JSON_parse_free (ppk_spec);
    398       GNUNET_break (0);
    399       return MHD_NO;
    400     }
    401     if (GNUNET_NO == res)
    402     {
    403       GNUNET_JSON_parse_free (spec);
    404       GNUNET_JSON_parse_free (ppk_spec);
    405       GNUNET_break_op (0);
    406       return TALER_MHD_reply_with_error (connection,
    407                                          MHD_HTTP_BAD_REQUEST,
    408                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
    409                                          "Unable to parse request body");
    410     }
    411 
    412     GNUNET_JSON_parse_free (ppk_spec);
    413   }
    414 
    415   /* check if there are num_of_participants - 1 commitments */
    416   if (dc->num_of_participants - 1 != json_array_size (commitments))
    417   {
    418     GNUNET_break_op (0);
    419     GNUNET_JSON_parse_free (spec);
    420 
    421     return TALER_MHD_reply_with_error (connection,
    422                                        MHD_HTTP_BAD_REQUEST,
    423                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
    424                                        "Number of commitments not matching");
    425   }
    426 
    427   /* parse all commitments */
    428   struct FROST_DkgCommitment dkg_commitments[dc->num_of_participants - 1];
    429   dc->dkg_commitments = dkg_commitments;
    430   json_t *coms = json_array ();
    431 
    432   // Place to store the delivered public keys to later encrypt our secret shares
    433   // against
    434   struct GNUNET_CRYPTO_EddsaPublicKey pub_sig_keys[dc->num_of_participants - 1];
    435 
    436   for (unsigned int i = 0; i < dc->num_of_participants - 1; i++)
    437   {
    438     if (GNUNET_OK != FROST_initialize_dkg_commitment (&dc->dkg_commitments[i],
    439                                                       dc->provider_index,
    440                                                       dc->threshold))
    441     {
    442       GNUNET_break (0);
    443       return TALER_MHD_reply_with_error (connection,
    444                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
    445                                          TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
    446                                          "Initialize DKG commitment");
    447     }
    448 
    449     json_t *json_temp = NULL;
    450     struct GNUNET_JSON_Specification com_spec[] = {
    451       GNUNET_JSON_spec_uint8 ("provider_index",
    452                               &dc->dkg_commitments[i].identifier),
    453       GNUNET_JSON_spec_json ("dkg_commitment",
    454                              &json_temp),
    455       GNUNET_JSON_spec_fixed_auto ("zkp_r",
    456                                    &dc->dkg_commitments[i].zkp.r),
    457       GNUNET_JSON_spec_fixed_auto ("zkp_z",
    458                                    &dc->dkg_commitments[i].zkp.z),
    459       GNUNET_JSON_spec_fixed_auto ("public_key",
    460                                    &pub_sig_keys[i]),
    461       GNUNET_JSON_spec_end ()
    462     };
    463 
    464     res = TALER_MHD_parse_json_array (connection,
    465                                       commitments,
    466                                       com_spec,
    467                                       i,
    468                                       -1);
    469 
    470     if (GNUNET_SYSERR == res)
    471     {
    472       GNUNET_JSON_parse_free (spec);
    473       GNUNET_JSON_parse_free (com_spec);
    474       FROST_free_dkg_commitment (dkg_commitments,
    475                                  dc->num_of_participants - 1);
    476       GNUNET_break (0);
    477       return MHD_NO;
    478     }
    479     if (GNUNET_NO == res)
    480     {
    481       GNUNET_JSON_parse_free (spec);
    482       GNUNET_JSON_parse_free (com_spec);
    483       FROST_free_dkg_commitment (dkg_commitments,
    484                                  dc->num_of_participants - 1);
    485       GNUNET_break_op (0);
    486       return TALER_MHD_reply_with_error (connection,
    487                                          MHD_HTTP_BAD_REQUEST,
    488                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
    489                                          "Unable to parse request body");
    490     }
    491 
    492     /* check if there are `threshold` commitment values */
    493     if (dc->threshold != json_array_size (json_temp))
    494     {
    495       GNUNET_JSON_parse_free (spec);
    496       GNUNET_JSON_parse_free (com_spec);
    497       FROST_free_dkg_commitment (dkg_commitments,
    498                                  dc->num_of_participants - 1);
    499       GNUNET_break_op (0);
    500       return TALER_MHD_reply_with_error (connection,
    501                                          MHD_HTTP_BAD_REQUEST,
    502                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
    503                                          "Number of commitment values not equal to threshold value");
    504     }
    505     dc->dkg_commitments[i].shares_commitments_length = dc->threshold;
    506 
    507     /* add temp value to json array */
    508     json_array_append_new (coms,
    509                            json_temp);
    510 
    511     /* parse the commitment values */
    512     for (unsigned int j = 0; j < dc->threshold; j++)
    513     {
    514       struct GNUNET_JSON_Specification coms_spec[] = {
    515         GNUNET_JSON_spec_fixed_auto (NULL,
    516                                      &dc->dkg_commitments[i].share_comm[j]),
    517         GNUNET_JSON_spec_end ()
    518       };
    519 
    520       res = TALER_MHD_parse_json_array (connection,
    521                                         json_array_get (coms,
    522                                                         i),
    523                                         coms_spec,
    524                                         j,
    525                                         -1);
    526 
    527       if (GNUNET_SYSERR == res)
    528       {
    529         GNUNET_JSON_parse_free (spec);
    530         GNUNET_JSON_parse_free (com_spec);
    531         GNUNET_JSON_parse_free (coms_spec);
    532         FROST_free_dkg_commitment (dkg_commitments,
    533                                    dc->num_of_participants - 1);
    534         GNUNET_break (0);
    535         return MHD_NO;
    536       }
    537       if (GNUNET_NO == res)
    538       {
    539         GNUNET_JSON_parse_free (spec);
    540         GNUNET_JSON_parse_free (com_spec);
    541         GNUNET_JSON_parse_free (coms_spec);
    542         FROST_free_dkg_commitment (dkg_commitments,
    543                                    dc->num_of_participants - 1);
    544         GNUNET_break_op (0);
    545         return TALER_MHD_reply_with_error (connection,
    546                                            MHD_HTTP_BAD_REQUEST,
    547                                            TALER_EC_GENERIC_PARAMETER_MALFORMED,
    548                                            "Unable to parse request body");
    549       }
    550 
    551       /* free json spec */
    552       GNUNET_JSON_parse_free (coms_spec);
    553     }
    554 
    555     /* free json spec */
    556     GNUNET_JSON_parse_free (com_spec);
    557   }
    558 
    559   /* free json spec */
    560   GNUNET_JSON_parse_free (spec);
    561 
    562   /* check if commitments are valid */
    563   for (unsigned int i = 0; i < dc->num_of_participants - 1; i++)
    564   {
    565     /* hash received pub key */
    566     struct FROST_HashState h_s;
    567     struct FROST_HashCode pub_key_hash;
    568     FROST_hash_init (&h_s);
    569     FROST_hash_fixed_update (&h_s,
    570                              &pub_sig_keys[i].q_y,
    571                              sizeof (pub_sig_keys[i].q_y));
    572     FROST_hash_final (&h_s,
    573                       &pub_key_hash);
    574 
    575     if (GNUNET_OK != FROST_keygen_validate_commitment (&dc->dkg_commitments[i],
    576                                                        &pub_key_hash,
    577                                                        dc->num_of_participants))
    578     {
    579       FROST_free_dkg_commitment (dkg_commitments,
    580                                  dc->num_of_participants - 1);
    581       GNUNET_break_op (0);
    582       return TALER_MHD_reply_with_error (connection,
    583                                          MHD_HTTP_BAD_REQUEST,
    584                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
    585                                          "Could not validate commitment");
    586     }
    587   }
    588 
    589   /* check if commitments are already stored */
    590   enum GNUNET_DB_QueryStatus qs;
    591   qs = db->lookup_dkg_commitment (db->cls,
    592                                   &dc->request_id);
    593 
    594   switch (qs)
    595   {
    596   case GNUNET_DB_STATUS_HARD_ERROR:
    597   case GNUNET_DB_STATUS_SOFT_ERROR:
    598     FROST_free_dkg_commitment (dkg_commitments,
    599                                dc->num_of_participants - 1);
    600     GNUNET_break (0);
    601     return TALER_MHD_reply_with_error (connection,
    602                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    603                                        TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
    604                                        "lookup dkg-commitment");
    605   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
    606     /* store commitments */
    607     MHD_RESULT mhd_res;
    608     mhd_res = store_commitments (dc);
    609     if (MHD_HTTP_OK != mhd_res)
    610     {
    611       FROST_free_dkg_commitment (dkg_commitments,
    612                                  dc->num_of_participants - 1);
    613       return mhd_res;
    614     }
    615     break;
    616   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
    617     // commitments are already stored - go ahead
    618     break;
    619   }
    620 
    621   FROST_free_dkg_commitment (dkg_commitments,
    622                              dc->num_of_participants - 1);
    623 
    624   /* derive the final context string */
    625   struct FROST_DkgContextString cs_h;
    626   if (GNUNET_YES != FROSIX_dkg_derive_context_string_ (
    627         &cs_h,
    628         dc->provider_index,
    629         dc->threshold,
    630         &dc->context_string,
    631         &dc->auth_hash,
    632         providers_public_keys,
    633         dc->num_of_participants,
    634         &dc->secret_provider_salt))
    635   {
    636     GNUNET_break (0);
    637     return TALER_MHD_reply_with_error (connection,
    638                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    639                                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
    640                                        "Derive context string");
    641   }
    642 
    643   /* create shares */
    644   struct FROST_DkgShare dkg_shares[dc->num_of_participants];
    645 
    646   if (GNUNET_OK != FROSIX_dkg_shares_generate_ (dkg_shares,
    647                                                 &cs_h,
    648                                                 NULL,
    649                                                 dc->provider_index,
    650                                                 dc->threshold,
    651                                                 dc->num_of_participants))
    652   {
    653     GNUNET_break (0);
    654     return TALER_MHD_reply_with_error (connection,
    655                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
    656                                        TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
    657                                        "Generate DKG shares");
    658   }
    659 
    660   res = return_dkg_shares (connection,
    661                            dkg_shares,
    662                            pub_sig_keys,
    663                            dc->provider_index,
    664                            dc->num_of_participants);
    665 
    666   return res;
    667 
    668 }