anastasis

Credential backup and recovery protocol and service
Log | Files | Refs | Submodules | README | LICENSE

anastasis_backup.c (29351B)


      1 /*
      2   This file is part of Anastasis
      3   Copyright (C) 2020, 2021 Anastasis SARL
      4 
      5   Anastasis 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   Anastasis 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   Anastasis; see the file COPYING.GPL.  If not, see <http://www.gnu.org/licenses/>
     15 */
     16 /**
     17  * @brief anastasis client api
     18  * @author Christian Grothoff
     19  * @author Dominik Meister
     20  * @author Dennis Neufeld
     21  */
     22 #include "platform.h"
     23 #include "anastasis.h"
     24 #include <taler/taler_merchant_service.h>
     25 #include <zlib.h>
     26 
     27 
     28 struct ANASTASIS_Truth
     29 {
     30   /**
     31    * Identification of the truth.
     32    */
     33   struct ANASTASIS_CRYPTO_TruthUUIDP uuid;
     34 
     35   /**
     36    * Keyshare of this truth, used to generate policy keys
     37    */
     38   struct ANASTASIS_CRYPTO_KeyShareP key_share;
     39 
     40   /**
     41    * Nonce used for the symmetric encryption.
     42    */
     43   struct ANASTASIS_CRYPTO_NonceP nonce;
     44 
     45   /**
     46    * Key used to encrypt this truth
     47    */
     48   struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
     49 
     50   /**
     51    * Server salt used to derive user identifier
     52    */
     53   struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt;
     54 
     55   /**
     56    * Server salt used to derive hash from security answer
     57    */
     58   struct ANASTASIS_CRYPTO_QuestionSaltP question_salt;
     59 
     60   /**
     61    * Url of the server
     62    */
     63   char *url;
     64 
     65   /**
     66    * Method used for this truth
     67    */
     68   char *type;
     69 
     70   /**
     71    * Instructions for the user to recover this truth.
     72    */
     73   char *instructions;
     74 
     75   /**
     76    * Mime type of the truth, NULL if not given.
     77    */
     78   char *mime_type;
     79 
     80 };
     81 
     82 
     83 struct ANASTASIS_Truth *
     84 ANASTASIS_truth_from_json (const json_t *json)
     85 {
     86   struct ANASTASIS_Truth *t = GNUNET_new (struct ANASTASIS_Truth);
     87   const char *url;
     88   const char *type;
     89   const char *instructions;
     90   const char *mime_type = NULL;
     91   struct GNUNET_JSON_Specification spec[] = {
     92     GNUNET_JSON_spec_string ("url",
     93                              &url),
     94     GNUNET_JSON_spec_string ("type",
     95                              &type),
     96     GNUNET_JSON_spec_string ("instructions",
     97                              &instructions),
     98     GNUNET_JSON_spec_mark_optional (
     99       GNUNET_JSON_spec_string ("mime_type",
    100                                &mime_type),
    101       NULL),
    102     GNUNET_JSON_spec_fixed_auto ("uuid",
    103                                  &t->uuid),
    104     GNUNET_JSON_spec_fixed_auto ("nonce",
    105                                  &t->nonce),
    106     GNUNET_JSON_spec_fixed_auto ("key_share",
    107                                  &t->key_share),
    108     GNUNET_JSON_spec_fixed_auto ("truth_key",
    109                                  &t->truth_key),
    110     GNUNET_JSON_spec_fixed_auto ("question_salt",
    111                                  &t->question_salt),
    112     GNUNET_JSON_spec_fixed_auto ("provider_salt",
    113                                  &t->provider_salt),
    114     GNUNET_JSON_spec_end ()
    115   };
    116 
    117   if (GNUNET_OK !=
    118       GNUNET_JSON_parse (json,
    119                          spec,
    120                          NULL, NULL))
    121   {
    122     GNUNET_break_op (0);
    123     GNUNET_free (t);
    124     return NULL;
    125   }
    126   t->url = GNUNET_strdup (url);
    127   t->type = GNUNET_strdup (type);
    128   t->instructions = GNUNET_strdup (instructions);
    129   if (NULL != mime_type)
    130     t->mime_type = GNUNET_strdup (mime_type);
    131   return t;
    132 }
    133 
    134 
    135 json_t *
    136 ANASTASIS_truth_to_json (const struct ANASTASIS_Truth *t)
    137 {
    138   return GNUNET_JSON_PACK (
    139     GNUNET_JSON_pack_data_auto ("uuid",
    140                                 &t->uuid),
    141     GNUNET_JSON_pack_data_auto ("key_share",
    142                                 &t->key_share),
    143     GNUNET_JSON_pack_data_auto ("truth_key",
    144                                 &t->truth_key),
    145     GNUNET_JSON_pack_data_auto ("question_salt",
    146                                 &t->question_salt),
    147     GNUNET_JSON_pack_data_auto ("nonce",
    148                                 &t->nonce),
    149     GNUNET_JSON_pack_data_auto ("provider_salt",
    150                                 &t->provider_salt),
    151     GNUNET_JSON_pack_string ("url",
    152                              t->url),
    153     GNUNET_JSON_pack_string ("type",
    154                              t->type),
    155     GNUNET_JSON_pack_string ("instructions",
    156                              t->instructions),
    157     GNUNET_JSON_pack_allow_null (
    158       GNUNET_JSON_pack_string ("mime_type",
    159                                t->mime_type)));
    160 }
    161 
    162 
    163 struct ANASTASIS_TruthUpload
    164 {
    165 
    166   /**
    167    * User identifier used for the keyshare encryption
    168    */
    169   struct ANASTASIS_CRYPTO_UserIdentifierP id;
    170 
    171   /**
    172    * CURL Context for the Post Request
    173    */
    174   struct GNUNET_CURL_Context *ctx;
    175 
    176   /**
    177    * Callback which sends back the generated truth object later used to build the policy
    178    */
    179   ANASTASIS_TruthCallback tc;
    180 
    181   /**
    182    * Closure for the Callback
    183    */
    184   void *tc_cls;
    185 
    186   /**
    187    * Reference to the Truthstore Operation
    188    */
    189   struct ANASTASIS_TruthStoreOperation *tso;
    190 
    191   /**
    192    * The truth we are uploading.
    193    */
    194   struct ANASTASIS_Truth *t;
    195 
    196 };
    197 
    198 
    199 /**
    200  * Function called with the result of trying to upload truth.
    201  *
    202  * @param cls our `struct ANASTASIS_TruthUpload`
    203  * @param ud details about the upload result
    204  */
    205 static void
    206 truth_store_callback (void *cls,
    207                       const struct ANASTASIS_UploadDetails *ud)
    208 {
    209   struct ANASTASIS_TruthUpload *tu = cls;
    210 
    211   tu->tso = NULL;
    212   tu->tc (tu->tc_cls,
    213           tu->t,
    214           ud);
    215   tu->t = NULL;
    216   ANASTASIS_truth_upload_cancel (tu);
    217 }
    218 
    219 
    220 struct ANASTASIS_TruthUpload *
    221 ANASTASIS_truth_upload3 (struct GNUNET_CURL_Context *ctx,
    222                          const struct ANASTASIS_CRYPTO_UserIdentifierP *user_id,
    223                          struct ANASTASIS_Truth *t,
    224                          const void *truth_data,
    225                          size_t truth_data_size,
    226                          uint32_t payment_years_requested,
    227                          struct GNUNET_TIME_Relative pay_timeout,
    228                          ANASTASIS_TruthCallback tc,
    229                          void *tc_cls)
    230 {
    231   struct ANASTASIS_TruthUpload *tu;
    232   struct ANASTASIS_CRYPTO_EncryptedKeyShareP encrypted_key_share;
    233   struct GNUNET_HashCode nt;
    234   void *encrypted_truth;
    235   size_t encrypted_truth_size;
    236 
    237   tu = GNUNET_new (struct ANASTASIS_TruthUpload);
    238   tu->tc = tc;
    239   tu->tc_cls = tc_cls;
    240   tu->ctx = ctx;
    241   tu->id = *user_id;
    242   tu->tc = tc;
    243   tu->tc_cls = tc_cls;
    244   tu->t = t;
    245 
    246   if (0 == strcmp ("question",
    247                    t->type))
    248   {
    249     char *answer;
    250 
    251     answer = GNUNET_strndup (truth_data,
    252                              truth_data_size);
    253     ANASTASIS_CRYPTO_secure_answer_hash (answer,
    254                                          &t->uuid,
    255                                          &t->question_salt,
    256                                          &nt);
    257     ANASTASIS_CRYPTO_keyshare_encrypt (&t->key_share,
    258                                        &tu->id,
    259                                        answer,
    260                                        &encrypted_key_share);
    261     GNUNET_free (answer);
    262     truth_data = &nt;
    263     truth_data_size = sizeof (nt);
    264   }
    265   else
    266   {
    267     ANASTASIS_CRYPTO_keyshare_encrypt (&t->key_share,
    268                                        &tu->id,
    269                                        NULL,
    270                                        &encrypted_key_share);
    271   }
    272   ANASTASIS_CRYPTO_truth_encrypt (&t->nonce,
    273                                   &t->truth_key,
    274                                   truth_data,
    275                                   truth_data_size,
    276                                   &encrypted_truth,
    277                                   &encrypted_truth_size);
    278   tu->tso = ANASTASIS_truth_store (tu->ctx,
    279                                    t->url,
    280                                    &t->uuid,
    281                                    t->type,
    282                                    &encrypted_key_share,
    283                                    t->mime_type,
    284                                    encrypted_truth_size,
    285                                    encrypted_truth,
    286                                    payment_years_requested,
    287                                    pay_timeout,
    288                                    &truth_store_callback,
    289                                    tu);
    290   GNUNET_free (encrypted_truth);
    291   if (NULL == tu->tso)
    292   {
    293     GNUNET_break (0);
    294     ANASTASIS_truth_free (t);
    295     ANASTASIS_truth_upload_cancel (tu);
    296     return NULL;
    297   }
    298   return tu;
    299 }
    300 
    301 
    302 struct ANASTASIS_TruthUpload *
    303 ANASTASIS_truth_upload2 (
    304   struct GNUNET_CURL_Context *ctx,
    305   const struct ANASTASIS_CRYPTO_UserIdentifierP *user_id,
    306   const char *provider_url,
    307   const char *type,
    308   const char *instructions,
    309   const char *mime_type,
    310   const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
    311   const void *truth_data,
    312   size_t truth_data_size,
    313   uint32_t payment_years_requested,
    314   struct GNUNET_TIME_Relative pay_timeout,
    315   const struct ANASTASIS_CRYPTO_NonceP *nonce,
    316   const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid,
    317   const struct ANASTASIS_CRYPTO_QuestionSaltP *question_salt,
    318   const struct ANASTASIS_CRYPTO_TruthKeyP *truth_key,
    319   const struct ANASTASIS_CRYPTO_KeyShareP *key_share,
    320   ANASTASIS_TruthCallback tc,
    321   void *tc_cls)
    322 {
    323   struct ANASTASIS_Truth *t;
    324 
    325   t = GNUNET_new (struct ANASTASIS_Truth);
    326   t->url = GNUNET_strdup (provider_url);
    327   t->type = GNUNET_strdup (type);
    328   t->instructions = (NULL != instructions)
    329                     ? GNUNET_strdup (instructions)
    330                     : NULL;
    331   t->mime_type = (NULL != mime_type)
    332                  ? GNUNET_strdup (mime_type)
    333                  : NULL;
    334   t->provider_salt = *provider_salt;
    335   t->question_salt = *question_salt;
    336   t->nonce = *nonce;
    337   t->uuid = *uuid;
    338   t->truth_key = *truth_key;
    339   t->key_share = *key_share;
    340   return ANASTASIS_truth_upload3 (ctx,
    341                                   user_id,
    342                                   t,
    343                                   truth_data,
    344                                   truth_data_size,
    345                                   payment_years_requested,
    346                                   pay_timeout,
    347                                   tc,
    348                                   tc_cls);
    349 }
    350 
    351 
    352 struct ANASTASIS_TruthUpload *
    353 ANASTASIS_truth_upload (
    354   struct GNUNET_CURL_Context *ctx,
    355   const struct ANASTASIS_CRYPTO_UserIdentifierP *user_id,
    356   const char *provider_url,
    357   const char *type,
    358   const char *instructions,
    359   const char *mime_type,
    360   const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt,
    361   const void *truth_data,
    362   size_t truth_data_size,
    363   uint32_t payment_years_requested,
    364   struct GNUNET_TIME_Relative pay_timeout,
    365   ANASTASIS_TruthCallback tc,
    366   void *tc_cls)
    367 {
    368   struct ANASTASIS_CRYPTO_QuestionSaltP question_salt;
    369   struct ANASTASIS_CRYPTO_TruthUUIDP uuid;
    370   struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
    371   struct ANASTASIS_CRYPTO_KeyShareP key_share;
    372   struct ANASTASIS_CRYPTO_NonceP nonce;
    373 
    374   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
    375                               &nonce,
    376                               sizeof (nonce));
    377   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
    378                               &question_salt,
    379                               sizeof (question_salt));
    380   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
    381                               &uuid,
    382                               sizeof (uuid));
    383   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
    384                               &truth_key,
    385                               sizeof (truth_key));
    386   ANASTASIS_CRYPTO_keyshare_create (&key_share);
    387   return ANASTASIS_truth_upload2 (ctx,
    388                                   user_id,
    389                                   provider_url,
    390                                   type,
    391                                   instructions,
    392                                   mime_type,
    393                                   provider_salt,
    394                                   truth_data,
    395                                   truth_data_size,
    396                                   payment_years_requested,
    397                                   pay_timeout,
    398                                   &nonce,
    399                                   &uuid,
    400                                   &question_salt,
    401                                   &truth_key,
    402                                   &key_share,
    403                                   tc,
    404                                   tc_cls);
    405 }
    406 
    407 
    408 void
    409 ANASTASIS_truth_upload_cancel (struct ANASTASIS_TruthUpload *tu)
    410 {
    411   if (NULL != tu->tso)
    412   {
    413     ANASTASIS_truth_store_cancel (tu->tso);
    414     tu->tso = NULL;
    415   }
    416   if (NULL != tu->t)
    417   {
    418     ANASTASIS_truth_free (tu->t);
    419     tu->t = NULL;
    420   }
    421   GNUNET_free (tu);
    422 }
    423 
    424 
    425 void
    426 ANASTASIS_truth_free (struct ANASTASIS_Truth *t)
    427 {
    428   GNUNET_free (t->url);
    429   GNUNET_free (t->type);
    430   GNUNET_free (t->instructions);
    431   GNUNET_free (t->mime_type);
    432   GNUNET_free (t);
    433 }
    434 
    435 
    436 struct ANASTASIS_Policy
    437 {
    438   /**
    439    * Encrypted policy master key
    440    */
    441   struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
    442 
    443   /**
    444    * Salt used to encrypt the master key
    445    */
    446   struct ANASTASIS_CRYPTO_MasterSaltP master_salt;
    447 
    448   /**
    449    * Array of truths
    450    */
    451   struct ANASTASIS_Truth **truths;
    452 
    453   /**
    454    * Length of @ truths array.
    455    */
    456   uint32_t truths_length;
    457 
    458 };
    459 
    460 
    461 /**
    462  * Duplicate truth object.
    463  *
    464  * @param t object to duplicate
    465  * @return copy of @a t
    466  */
    467 static struct ANASTASIS_Truth *
    468 truth_dup (const struct ANASTASIS_Truth *t)
    469 {
    470   struct ANASTASIS_Truth *d = GNUNET_new (struct ANASTASIS_Truth);
    471 
    472   *d = *t;
    473   d->url = GNUNET_strdup (t->url);
    474   d->type = GNUNET_strdup (t->type);
    475   d->instructions = GNUNET_strdup (t->instructions);
    476   if (NULL != t->mime_type)
    477     d->mime_type = GNUNET_strdup (t->mime_type);
    478   return d;
    479 }
    480 
    481 
    482 struct ANASTASIS_Policy *
    483 ANASTASIS_policy_create (const struct ANASTASIS_Truth *truths[],
    484                          unsigned int truths_len)
    485 {
    486   struct ANASTASIS_Policy *p;
    487 
    488   p = GNUNET_new (struct ANASTASIS_Policy);
    489   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
    490                               &p->master_salt,
    491                               sizeof (p->master_salt));
    492   {
    493     struct ANASTASIS_CRYPTO_KeyShareP key_shares[truths_len];
    494 
    495     for (unsigned int i = 0; i < truths_len; i++)
    496       key_shares[i] = truths[i]->key_share;
    497     ANASTASIS_CRYPTO_policy_key_derive (key_shares,
    498                                         truths_len,
    499                                         &p->master_salt,
    500                                         &p->policy_key);
    501   }
    502   p->truths = GNUNET_new_array (truths_len,
    503                                 struct ANASTASIS_Truth *);
    504   for (unsigned int i = 0; i<truths_len; i++)
    505     p->truths[i] = truth_dup (truths[i]);
    506   p->truths_length = truths_len;
    507   return p;
    508 }
    509 
    510 
    511 void
    512 ANASTASIS_policy_destroy (struct ANASTASIS_Policy *p)
    513 {
    514   for (unsigned int i = 0; i<p->truths_length; i++)
    515     ANASTASIS_truth_free (p->truths[i]);
    516   GNUNET_free (p->truths);
    517   GNUNET_free (p);
    518 }
    519 
    520 
    521 /**
    522  * State for a "policy store" CMD.
    523  */
    524 struct PolicyStoreState
    525 {
    526   /**
    527    * User identifier used as entropy source for the account public key
    528    */
    529   struct ANASTASIS_CRYPTO_UserIdentifierP id;
    530 
    531   /**
    532    * Hash of the current upload.  Used to check the server's response.
    533    */
    534   struct GNUNET_HashCode curr_hash;
    535 
    536   /**
    537    * Payment identifier.
    538    */
    539   struct ANASTASIS_PaymentSecretP payment_secret;
    540 
    541   /**
    542    * Server salt. Points into a truth object from which we got the
    543    * salt.
    544    */
    545   struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt;
    546 
    547   /**
    548    * The /policy POST operation handle.
    549    */
    550   struct ANASTASIS_PolicyStoreOperation *pso;
    551 
    552   /**
    553    * URL of the anastasis backend.
    554    */
    555   char *anastasis_url;
    556 
    557   /**
    558    * Payment request returned by this provider, if any.
    559    */
    560   char *payment_request;
    561 
    562   /**
    563    * reference to SecretShare
    564    */
    565   struct ANASTASIS_SecretShare *ss;
    566 
    567   /**
    568    * Version of the policy created at the provider.
    569    */
    570   unsigned long long policy_version;
    571 
    572   /**
    573    * When will the policy expire at the provider.
    574    */
    575   struct GNUNET_TIME_Timestamp policy_expiration;
    576 
    577 };
    578 
    579 /**
    580 * Defines a recovery document upload process (recovery document consists of multiple policies)
    581 */
    582 struct ANASTASIS_SecretShare
    583 {
    584   /**
    585    * Closure for the Result Callback
    586    */
    587   struct GNUNET_CURL_Context *ctx;
    588 
    589   /**
    590    * Callback which gives back the result of the POST Request
    591    */
    592   ANASTASIS_ShareResultCallback src;
    593 
    594   /**
    595    * Closure for the Result Callback
    596    */
    597   void *src_cls;
    598 
    599   /**
    600    * References for the upload states and operations (size of truths passed)
    601    */
    602   struct PolicyStoreState *pss;
    603 
    604   /**
    605    * Closure for the Result Callback
    606    */
    607   unsigned int pss_length;
    608 };
    609 
    610 
    611 /**
    612  * Callback to process a POST /policy request
    613  *
    614  * @param cls closure
    615  * @param ud the decoded response body
    616  */
    617 static void
    618 policy_store_cb (void *cls,
    619                  const struct ANASTASIS_UploadDetails *ud)
    620 {
    621   struct PolicyStoreState *pss = cls;
    622   struct ANASTASIS_SecretShare *ss = pss->ss;
    623   enum ANASTASIS_UploadStatus us;
    624 
    625   pss->pso = NULL;
    626   us = ud->us;
    627   if ( (ANASTASIS_US_SUCCESS == us) &&
    628        (0 != GNUNET_memcmp (&pss->curr_hash,
    629                             ud->details.success.curr_backup_hash)) )
    630   {
    631     GNUNET_break_op (0);
    632     us = ANASTASIS_US_SERVER_ERROR;
    633   }
    634   switch (us)
    635   {
    636   case ANASTASIS_US_SUCCESS:
    637     pss->policy_version = ud->details.success.policy_version;
    638     pss->policy_expiration = ud->details.success.policy_expiration;
    639     break;
    640   case ANASTASIS_US_PAYMENT_REQUIRED:
    641     pss->payment_request = GNUNET_strdup (ud->details.payment.payment_request);
    642     pss->payment_secret = ud->details.payment.ps;
    643     break;
    644   case ANASTASIS_US_HTTP_ERROR:
    645   case ANASTASIS_US_CLIENT_ERROR:
    646   case ANASTASIS_US_SERVER_ERROR:
    647     {
    648       struct ANASTASIS_ShareResult sr = {
    649         .ss = ANASTASIS_SHARE_STATUS_PROVIDER_FAILED,
    650         .details.provider_failure.provider_url = pss->anastasis_url,
    651         .details.provider_failure.http_status = ud->http_status,
    652         .details.provider_failure.ec = ud->ec,
    653       };
    654 
    655       ss->src (ss->src_cls,
    656                &sr);
    657       ANASTASIS_secret_share_cancel (ss);
    658       return;
    659     }
    660   case ANASTASIS_US_CONFLICTING_TRUTH:
    661     GNUNET_break (0);
    662     break;
    663   }
    664   for (unsigned int i = 0; i<ss->pss_length; i++)
    665     if (NULL != ss->pss[i].pso)
    666       /* some upload is still pending, let's wait for it to finish */
    667       return;
    668 
    669   {
    670     struct ANASTASIS_SharePaymentRequest spr[GNUNET_NZL (ss->pss_length)];
    671     struct ANASTASIS_ProviderSuccessStatus apss[GNUNET_NZL (ss->pss_length)];
    672     unsigned int off = 0;
    673     unsigned int voff = 0;
    674     struct ANASTASIS_ShareResult sr;
    675 
    676     for (unsigned int i = 0; i<ss->pss_length; i++)
    677     {
    678       struct PolicyStoreState *pssi = &ss->pss[i];
    679 
    680       if (NULL == pssi->payment_request)
    681       {
    682         apss[voff].policy_version = pssi->policy_version;
    683         apss[voff].provider_url = pssi->anastasis_url;
    684         apss[voff].policy_expiration = pssi->policy_expiration;
    685         voff++;
    686       }
    687       else
    688       {
    689         spr[off].payment_request_url = pssi->payment_request;
    690         spr[off].provider_url = pssi->anastasis_url;
    691         spr[off].payment_secret = pssi->payment_secret;
    692         off++;
    693       }
    694     }
    695     if (off > 0)
    696     {
    697       sr.ss = ANASTASIS_SHARE_STATUS_PAYMENT_REQUIRED;
    698       sr.details.payment_required.payment_requests = spr;
    699       sr.details.payment_required.payment_requests_length = off;
    700     }
    701     else
    702     {
    703       sr.ss = ANASTASIS_SHARE_STATUS_SUCCESS;
    704       sr.details.success.pss = apss;
    705       sr.details.success.num_providers = voff;
    706     }
    707     ss->src (ss->src_cls,
    708              &sr);
    709   }
    710   ANASTASIS_secret_share_cancel (ss);
    711 }
    712 
    713 
    714 struct ANASTASIS_SecretShare *
    715 ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
    716                         const json_t *id_data,
    717                         const struct ANASTASIS_ProviderDetails providers[],
    718                         unsigned int pss_length,
    719                         const struct ANASTASIS_Policy *policies[],
    720                         unsigned int policies_len,
    721                         uint32_t payment_years_requested,
    722                         struct GNUNET_TIME_Relative pay_timeout,
    723                         ANASTASIS_ShareResultCallback src,
    724                         void *src_cls,
    725                         const char *secret_name,
    726                         const void *core_secret,
    727                         size_t core_secret_size)
    728 {
    729   struct ANASTASIS_SecretShare *ss;
    730   struct ANASTASIS_CoreSecretEncryptionResult *cser;
    731   json_t *dec_policies;
    732   json_t *esc_methods;
    733   size_t recovery_document_size;
    734   char *recovery_document_str;
    735   size_t meta_size;
    736   void *meta;
    737 
    738   if (0 == pss_length)
    739   {
    740     GNUNET_break (0);
    741     return NULL;
    742   }
    743   ss = GNUNET_new (struct ANASTASIS_SecretShare);
    744   ss->src = src;
    745   ss->src_cls = src_cls;
    746   ss->pss = GNUNET_new_array (pss_length,
    747                               struct PolicyStoreState);
    748   ss->pss_length = pss_length;
    749   ss->ctx = ctx;
    750 
    751   {
    752     struct ANASTASIS_CRYPTO_PolicyKeyP policy_keys[GNUNET_NZL (policies_len)];
    753 
    754     for (unsigned int i = 0; i < policies_len; i++)
    755       policy_keys[i] = policies[i]->policy_key;
    756     cser = ANASTASIS_CRYPTO_core_secret_encrypt (policy_keys,
    757                                                  policies_len,
    758                                                  core_secret,
    759                                                  core_secret_size);
    760   }
    761   dec_policies = json_array ();
    762   GNUNET_assert (NULL != dec_policies);
    763   for (unsigned int k = 0; k < policies_len; k++)
    764   {
    765     const struct ANASTASIS_Policy *policy = policies[k];
    766     json_t *uuids = json_array ();
    767 
    768     GNUNET_assert (NULL != uuids);
    769     for (unsigned int b = 0; b < policy->truths_length; b++)
    770       GNUNET_assert (0 ==
    771                      json_array_append_new (
    772                        uuids,
    773                        GNUNET_JSON_from_data_auto (
    774                          &policy->truths[b]->uuid)));
    775     GNUNET_assert (0 ==
    776                    json_array_append_new (
    777                      dec_policies,
    778                      GNUNET_JSON_PACK (
    779                        GNUNET_JSON_pack_data_varsize ("master_key",
    780                                                       cser->enc_master_keys[k],
    781                                                       cser->enc_master_key_sizes
    782                                                       [k]),
    783                        GNUNET_JSON_pack_array_steal ("uuids",
    784                                                      uuids),
    785                        GNUNET_JSON_pack_data_auto ("master_salt",
    786                                                    &policy->master_salt))));
    787   }
    788 
    789   esc_methods = json_array ();
    790   GNUNET_assert (NULL != esc_methods);
    791   for (unsigned int k = 0; k < policies_len; k++)
    792   {
    793     const struct ANASTASIS_Policy *policy = policies[k];
    794 
    795     for (unsigned int l = 0; l < policy->truths_length; l++)
    796     {
    797       const struct ANASTASIS_Truth *pt = policy->truths[l];
    798       bool unique = true;
    799 
    800       /* Only append each truth once */
    801       for (unsigned int k2 = 0; k2 < k; k2++)
    802       {
    803         const struct ANASTASIS_Policy *p2 = policies[k2];
    804         for (unsigned int l2 = 0; l2 < p2->truths_length; l2++)
    805           if (0 ==
    806               GNUNET_memcmp (&pt->uuid,
    807                              &p2->truths[l2]->uuid))
    808           {
    809             unique = false;
    810             break;
    811           }
    812         if (! unique)
    813           break;
    814       }
    815       if (! unique)
    816         continue;
    817 
    818       GNUNET_assert (0 ==
    819                      json_array_append_new (
    820                        esc_methods,
    821                        GNUNET_JSON_PACK (
    822                          GNUNET_JSON_pack_data_auto ("uuid",
    823                                                      &pt->uuid),
    824                          GNUNET_JSON_pack_string ("url",
    825                                                   pt->url),
    826                          GNUNET_JSON_pack_string ("instructions",
    827                                                   pt->instructions),
    828                          GNUNET_JSON_pack_data_auto ("truth_key",
    829                                                      &pt->truth_key),
    830                          GNUNET_JSON_pack_data_auto ("question_salt",
    831                                                      &pt->question_salt),
    832                          GNUNET_JSON_pack_data_auto ("provider_salt",
    833                                                      &pt->provider_salt),
    834                          GNUNET_JSON_pack_string ("escrow_type",
    835                                                   pt->type))));
    836     }
    837   }
    838 
    839   {
    840     json_t *recovery_document;
    841     size_t rd_size;
    842     char *rd_str;
    843     Bytef *cbuf;
    844     uLongf cbuf_size;
    845     int ret;
    846     uint32_t be_size;
    847 
    848     recovery_document = GNUNET_JSON_PACK (
    849       GNUNET_JSON_pack_allow_null (
    850         GNUNET_JSON_pack_string ("secret_name",
    851                                  secret_name)),
    852       GNUNET_JSON_pack_array_steal ("policies",
    853                                     dec_policies),
    854       GNUNET_JSON_pack_array_steal ("escrow_methods",
    855                                     esc_methods),
    856       GNUNET_JSON_pack_data_varsize ("encrypted_core_secret",
    857                                      cser->enc_core_secret,
    858                                      cser->enc_core_secret_size));
    859     GNUNET_assert (NULL != recovery_document);
    860     ANASTASIS_CRYPTO_destroy_encrypted_core_secret (cser);
    861     cser = NULL;
    862 
    863     rd_str = json_dumps (recovery_document,
    864                          JSON_COMPACT | JSON_SORT_KEYS);
    865     GNUNET_assert (NULL != rd_str);
    866     json_decref (recovery_document);
    867     rd_size = strlen (rd_str);
    868     cbuf_size = compressBound (rd_size);
    869     be_size = htonl ((uint32_t) rd_size);
    870     cbuf = GNUNET_malloc (cbuf_size + sizeof (uint32_t));
    871     memcpy (cbuf,
    872             &be_size,
    873             sizeof (uint32_t));
    874     ret = compress (cbuf + sizeof (uint32_t),
    875                     &cbuf_size,
    876                     (const Bytef *) rd_str,
    877                     rd_size);
    878     if (Z_OK != ret)
    879     {
    880       /* compression failed!? */
    881       GNUNET_break (0);
    882       free (rd_str);
    883       GNUNET_free (cbuf);
    884       ANASTASIS_secret_share_cancel (ss);
    885       return NULL;
    886     }
    887     free (rd_str);
    888     recovery_document_size = (size_t) (cbuf_size + sizeof (uint32_t));
    889     recovery_document_str = (char *) cbuf;
    890   }
    891 
    892   meta_size = sizeof (struct GNUNET_HashCode);
    893   if (NULL != secret_name)
    894     meta_size += strlen (secret_name) + 1;
    895   meta = GNUNET_malloc (meta_size);
    896   GNUNET_CRYPTO_hash (recovery_document_str,
    897                       recovery_document_size,
    898                       (struct GNUNET_HashCode *) meta);
    899   if (NULL != secret_name)
    900     memcpy (meta + sizeof (struct GNUNET_HashCode),
    901             secret_name,
    902             strlen (secret_name) + 1);
    903 
    904   for (unsigned int l = 0; l < ss->pss_length; l++)
    905   {
    906     struct PolicyStoreState *pss = &ss->pss[l];
    907     void *recovery_data;
    908     size_t recovery_data_size;
    909     struct ANASTASIS_CRYPTO_AccountPrivateKeyP anastasis_priv;
    910     size_t enc_meta_size = 0;
    911     void *enc_meta = NULL;
    912 
    913     pss->ss = ss;
    914     pss->anastasis_url = GNUNET_strdup (providers[l].provider_url);
    915     pss->provider_salt = providers[l].provider_salt;
    916     pss->payment_secret = providers[l].payment_secret;
    917     ANASTASIS_CRYPTO_user_identifier_derive (id_data,
    918                                              &pss->provider_salt,
    919                                              &pss->id);
    920     ANASTASIS_CRYPTO_recovery_metadata_encrypt (&pss->id,
    921                                                 meta,
    922                                                 meta_size,
    923                                                 &enc_meta,
    924                                                 &enc_meta_size);
    925     ANASTASIS_CRYPTO_account_private_key_derive (&pss->id,
    926                                                  &anastasis_priv);
    927     ANASTASIS_CRYPTO_recovery_document_encrypt (&pss->id,
    928                                                 recovery_document_str,
    929                                                 recovery_document_size,
    930                                                 &recovery_data,
    931                                                 &recovery_data_size);
    932     GNUNET_CRYPTO_hash (recovery_data,
    933                         recovery_data_size,
    934                         &pss->curr_hash);
    935     pss->pso = ANASTASIS_policy_store (
    936       ss->ctx,
    937       pss->anastasis_url,
    938       &anastasis_priv,
    939       recovery_data,
    940       recovery_data_size,
    941       enc_meta,
    942       enc_meta_size,
    943       payment_years_requested,
    944       (! GNUNET_is_zero (&pss->payment_secret))
    945       ? &pss->payment_secret
    946       : NULL,
    947       pay_timeout,
    948       &policy_store_cb,
    949       pss);
    950     GNUNET_free (recovery_data);
    951     GNUNET_free (enc_meta);
    952     if (NULL == pss->pso)
    953     {
    954       GNUNET_break (0);
    955       ANASTASIS_secret_share_cancel (ss);
    956       GNUNET_free (recovery_document_str);
    957       GNUNET_free (meta);
    958       return NULL;
    959     }
    960   }
    961   GNUNET_free (meta);
    962   GNUNET_free (recovery_document_str);
    963   return ss;
    964 }
    965 
    966 
    967 void
    968 ANASTASIS_secret_share_cancel (struct ANASTASIS_SecretShare *ss)
    969 {
    970   for (unsigned int i = 0; i<ss->pss_length; i++)
    971   {
    972     struct PolicyStoreState *pssi = &ss->pss[i];
    973 
    974     if (NULL != pssi->pso)
    975     {
    976       ANASTASIS_policy_store_cancel (pssi->pso);
    977       pssi->pso = NULL;
    978     }
    979     GNUNET_free (pssi->anastasis_url);
    980     GNUNET_free (pssi->payment_request);
    981   }
    982   GNUNET_free (ss->pss);
    983   GNUNET_free (ss);
    984 }