anastasis

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

anastasis_backup.c (29055B)


      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 (&nonce,
    375                               sizeof (nonce));
    376   GNUNET_CRYPTO_random_block (&question_salt,
    377                               sizeof (question_salt));
    378   GNUNET_CRYPTO_random_block (&uuid,
    379                               sizeof (uuid));
    380   GNUNET_CRYPTO_random_block (&truth_key,
    381                               sizeof (truth_key));
    382   ANASTASIS_CRYPTO_keyshare_create (&key_share);
    383   return ANASTASIS_truth_upload2 (ctx,
    384                                   user_id,
    385                                   provider_url,
    386                                   type,
    387                                   instructions,
    388                                   mime_type,
    389                                   provider_salt,
    390                                   truth_data,
    391                                   truth_data_size,
    392                                   payment_years_requested,
    393                                   pay_timeout,
    394                                   &nonce,
    395                                   &uuid,
    396                                   &question_salt,
    397                                   &truth_key,
    398                                   &key_share,
    399                                   tc,
    400                                   tc_cls);
    401 }
    402 
    403 
    404 void
    405 ANASTASIS_truth_upload_cancel (struct ANASTASIS_TruthUpload *tu)
    406 {
    407   if (NULL != tu->tso)
    408   {
    409     ANASTASIS_truth_store_cancel (tu->tso);
    410     tu->tso = NULL;
    411   }
    412   if (NULL != tu->t)
    413   {
    414     ANASTASIS_truth_free (tu->t);
    415     tu->t = NULL;
    416   }
    417   GNUNET_free (tu);
    418 }
    419 
    420 
    421 void
    422 ANASTASIS_truth_free (struct ANASTASIS_Truth *t)
    423 {
    424   GNUNET_free (t->url);
    425   GNUNET_free (t->type);
    426   GNUNET_free (t->instructions);
    427   GNUNET_free (t->mime_type);
    428   GNUNET_free (t);
    429 }
    430 
    431 
    432 struct ANASTASIS_Policy
    433 {
    434   /**
    435    * Encrypted policy master key
    436    */
    437   struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
    438 
    439   /**
    440    * Salt used to encrypt the master key
    441    */
    442   struct ANASTASIS_CRYPTO_MasterSaltP master_salt;
    443 
    444   /**
    445    * Array of truths
    446    */
    447   struct ANASTASIS_Truth **truths;
    448 
    449   /**
    450    * Length of @ truths array.
    451    */
    452   uint32_t truths_length;
    453 
    454 };
    455 
    456 
    457 /**
    458  * Duplicate truth object.
    459  *
    460  * @param t object to duplicate
    461  * @return copy of @a t
    462  */
    463 static struct ANASTASIS_Truth *
    464 truth_dup (const struct ANASTASIS_Truth *t)
    465 {
    466   struct ANASTASIS_Truth *d = GNUNET_new (struct ANASTASIS_Truth);
    467 
    468   *d = *t;
    469   d->url = GNUNET_strdup (t->url);
    470   d->type = GNUNET_strdup (t->type);
    471   d->instructions = GNUNET_strdup (t->instructions);
    472   if (NULL != t->mime_type)
    473     d->mime_type = GNUNET_strdup (t->mime_type);
    474   return d;
    475 }
    476 
    477 
    478 struct ANASTASIS_Policy *
    479 ANASTASIS_policy_create (const struct ANASTASIS_Truth *truths[],
    480                          unsigned int truths_len)
    481 {
    482   struct ANASTASIS_Policy *p;
    483 
    484   p = GNUNET_new (struct ANASTASIS_Policy);
    485   GNUNET_CRYPTO_random_block (&p->master_salt,
    486                               sizeof (p->master_salt));
    487   {
    488     struct ANASTASIS_CRYPTO_KeyShareP key_shares[truths_len];
    489 
    490     for (unsigned int i = 0; i < truths_len; i++)
    491       key_shares[i] = truths[i]->key_share;
    492     ANASTASIS_CRYPTO_policy_key_derive (key_shares,
    493                                         truths_len,
    494                                         &p->master_salt,
    495                                         &p->policy_key);
    496   }
    497   p->truths = GNUNET_new_array (truths_len,
    498                                 struct ANASTASIS_Truth *);
    499   for (unsigned int i = 0; i<truths_len; i++)
    500     p->truths[i] = truth_dup (truths[i]);
    501   p->truths_length = truths_len;
    502   return p;
    503 }
    504 
    505 
    506 void
    507 ANASTASIS_policy_destroy (struct ANASTASIS_Policy *p)
    508 {
    509   for (unsigned int i = 0; i<p->truths_length; i++)
    510     ANASTASIS_truth_free (p->truths[i]);
    511   GNUNET_free (p->truths);
    512   GNUNET_free (p);
    513 }
    514 
    515 
    516 /**
    517  * State for a "policy store" CMD.
    518  */
    519 struct PolicyStoreState
    520 {
    521   /**
    522    * User identifier used as entropy source for the account public key
    523    */
    524   struct ANASTASIS_CRYPTO_UserIdentifierP id;
    525 
    526   /**
    527    * Hash of the current upload.  Used to check the server's response.
    528    */
    529   struct GNUNET_HashCode curr_hash;
    530 
    531   /**
    532    * Payment identifier.
    533    */
    534   struct ANASTASIS_PaymentSecretP payment_secret;
    535 
    536   /**
    537    * Server salt. Points into a truth object from which we got the
    538    * salt.
    539    */
    540   struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt;
    541 
    542   /**
    543    * The /policy POST operation handle.
    544    */
    545   struct ANASTASIS_PolicyStoreOperation *pso;
    546 
    547   /**
    548    * URL of the anastasis backend.
    549    */
    550   char *anastasis_url;
    551 
    552   /**
    553    * Payment request returned by this provider, if any.
    554    */
    555   char *payment_request;
    556 
    557   /**
    558    * reference to SecretShare
    559    */
    560   struct ANASTASIS_SecretShare *ss;
    561 
    562   /**
    563    * Version of the policy created at the provider.
    564    */
    565   unsigned long long policy_version;
    566 
    567   /**
    568    * When will the policy expire at the provider.
    569    */
    570   struct GNUNET_TIME_Timestamp policy_expiration;
    571 
    572 };
    573 
    574 /**
    575 * Defines a recovery document upload process (recovery document consists of multiple policies)
    576 */
    577 struct ANASTASIS_SecretShare
    578 {
    579   /**
    580    * Closure for the Result Callback
    581    */
    582   struct GNUNET_CURL_Context *ctx;
    583 
    584   /**
    585    * Callback which gives back the result of the POST Request
    586    */
    587   ANASTASIS_ShareResultCallback src;
    588 
    589   /**
    590    * Closure for the Result Callback
    591    */
    592   void *src_cls;
    593 
    594   /**
    595    * References for the upload states and operations (size of truths passed)
    596    */
    597   struct PolicyStoreState *pss;
    598 
    599   /**
    600    * Closure for the Result Callback
    601    */
    602   unsigned int pss_length;
    603 };
    604 
    605 
    606 /**
    607  * Callback to process a POST /policy request
    608  *
    609  * @param cls closure
    610  * @param ud the decoded response body
    611  */
    612 static void
    613 policy_store_cb (void *cls,
    614                  const struct ANASTASIS_UploadDetails *ud)
    615 {
    616   struct PolicyStoreState *pss = cls;
    617   struct ANASTASIS_SecretShare *ss = pss->ss;
    618   enum ANASTASIS_UploadStatus us;
    619 
    620   pss->pso = NULL;
    621   us = ud->us;
    622   if ( (ANASTASIS_US_SUCCESS == us) &&
    623        (0 != GNUNET_memcmp (&pss->curr_hash,
    624                             ud->details.success.curr_backup_hash)) )
    625   {
    626     GNUNET_break_op (0);
    627     us = ANASTASIS_US_SERVER_ERROR;
    628   }
    629   switch (us)
    630   {
    631   case ANASTASIS_US_SUCCESS:
    632     pss->policy_version = ud->details.success.policy_version;
    633     pss->policy_expiration = ud->details.success.policy_expiration;
    634     break;
    635   case ANASTASIS_US_PAYMENT_REQUIRED:
    636     pss->payment_request = GNUNET_strdup (ud->details.payment.payment_request);
    637     pss->payment_secret = ud->details.payment.ps;
    638     break;
    639   case ANASTASIS_US_HTTP_ERROR:
    640   case ANASTASIS_US_CLIENT_ERROR:
    641   case ANASTASIS_US_SERVER_ERROR:
    642     {
    643       struct ANASTASIS_ShareResult sr = {
    644         .ss = ANASTASIS_SHARE_STATUS_PROVIDER_FAILED,
    645         .details.provider_failure.provider_url = pss->anastasis_url,
    646         .details.provider_failure.http_status = ud->http_status,
    647         .details.provider_failure.ec = ud->ec,
    648       };
    649 
    650       ss->src (ss->src_cls,
    651                &sr);
    652       ANASTASIS_secret_share_cancel (ss);
    653       return;
    654     }
    655   case ANASTASIS_US_CONFLICTING_TRUTH:
    656     GNUNET_break (0);
    657     break;
    658   }
    659   for (unsigned int i = 0; i<ss->pss_length; i++)
    660     if (NULL != ss->pss[i].pso)
    661       /* some upload is still pending, let's wait for it to finish */
    662       return;
    663 
    664   {
    665     struct ANASTASIS_SharePaymentRequest spr[GNUNET_NZL (ss->pss_length)];
    666     struct ANASTASIS_ProviderSuccessStatus apss[GNUNET_NZL (ss->pss_length)];
    667     unsigned int off = 0;
    668     unsigned int voff = 0;
    669     struct ANASTASIS_ShareResult sr;
    670 
    671     for (unsigned int i = 0; i<ss->pss_length; i++)
    672     {
    673       struct PolicyStoreState *pssi = &ss->pss[i];
    674 
    675       if (NULL == pssi->payment_request)
    676       {
    677         apss[voff].policy_version = pssi->policy_version;
    678         apss[voff].provider_url = pssi->anastasis_url;
    679         apss[voff].policy_expiration = pssi->policy_expiration;
    680         voff++;
    681       }
    682       else
    683       {
    684         spr[off].payment_request_url = pssi->payment_request;
    685         spr[off].provider_url = pssi->anastasis_url;
    686         spr[off].payment_secret = pssi->payment_secret;
    687         off++;
    688       }
    689     }
    690     if (off > 0)
    691     {
    692       sr.ss = ANASTASIS_SHARE_STATUS_PAYMENT_REQUIRED;
    693       sr.details.payment_required.payment_requests = spr;
    694       sr.details.payment_required.payment_requests_length = off;
    695     }
    696     else
    697     {
    698       sr.ss = ANASTASIS_SHARE_STATUS_SUCCESS;
    699       sr.details.success.pss = apss;
    700       sr.details.success.num_providers = voff;
    701     }
    702     ss->src (ss->src_cls,
    703              &sr);
    704   }
    705   ANASTASIS_secret_share_cancel (ss);
    706 }
    707 
    708 
    709 struct ANASTASIS_SecretShare *
    710 ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
    711                         const json_t *id_data,
    712                         const struct ANASTASIS_ProviderDetails providers[],
    713                         unsigned int pss_length,
    714                         const struct ANASTASIS_Policy *policies[],
    715                         unsigned int policies_len,
    716                         uint32_t payment_years_requested,
    717                         struct GNUNET_TIME_Relative pay_timeout,
    718                         ANASTASIS_ShareResultCallback src,
    719                         void *src_cls,
    720                         const char *secret_name,
    721                         const void *core_secret,
    722                         size_t core_secret_size)
    723 {
    724   struct ANASTASIS_SecretShare *ss;
    725   struct ANASTASIS_CoreSecretEncryptionResult *cser;
    726   json_t *dec_policies;
    727   json_t *esc_methods;
    728   size_t recovery_document_size;
    729   char *recovery_document_str;
    730   size_t meta_size;
    731   void *meta;
    732 
    733   if (0 == pss_length)
    734   {
    735     GNUNET_break (0);
    736     return NULL;
    737   }
    738   ss = GNUNET_new (struct ANASTASIS_SecretShare);
    739   ss->src = src;
    740   ss->src_cls = src_cls;
    741   ss->pss = GNUNET_new_array (pss_length,
    742                               struct PolicyStoreState);
    743   ss->pss_length = pss_length;
    744   ss->ctx = ctx;
    745 
    746   {
    747     struct ANASTASIS_CRYPTO_PolicyKeyP policy_keys[GNUNET_NZL (policies_len)];
    748 
    749     for (unsigned int i = 0; i < policies_len; i++)
    750       policy_keys[i] = policies[i]->policy_key;
    751     cser = ANASTASIS_CRYPTO_core_secret_encrypt (policy_keys,
    752                                                  policies_len,
    753                                                  core_secret,
    754                                                  core_secret_size);
    755   }
    756   dec_policies = json_array ();
    757   GNUNET_assert (NULL != dec_policies);
    758   for (unsigned int k = 0; k < policies_len; k++)
    759   {
    760     const struct ANASTASIS_Policy *policy = policies[k];
    761     json_t *uuids = json_array ();
    762 
    763     GNUNET_assert (NULL != uuids);
    764     for (unsigned int b = 0; b < policy->truths_length; b++)
    765       GNUNET_assert (0 ==
    766                      json_array_append_new (
    767                        uuids,
    768                        GNUNET_JSON_from_data_auto (
    769                          &policy->truths[b]->uuid)));
    770     GNUNET_assert (0 ==
    771                    json_array_append_new (
    772                      dec_policies,
    773                      GNUNET_JSON_PACK (
    774                        GNUNET_JSON_pack_data_varsize ("master_key",
    775                                                       cser->enc_master_keys[k],
    776                                                       cser->enc_master_key_sizes
    777                                                       [k]),
    778                        GNUNET_JSON_pack_array_steal ("uuids",
    779                                                      uuids),
    780                        GNUNET_JSON_pack_data_auto ("master_salt",
    781                                                    &policy->master_salt))));
    782   }
    783 
    784   esc_methods = json_array ();
    785   GNUNET_assert (NULL != esc_methods);
    786   for (unsigned int k = 0; k < policies_len; k++)
    787   {
    788     const struct ANASTASIS_Policy *policy = policies[k];
    789 
    790     for (unsigned int l = 0; l < policy->truths_length; l++)
    791     {
    792       const struct ANASTASIS_Truth *pt = policy->truths[l];
    793       bool unique = true;
    794 
    795       /* Only append each truth once */
    796       for (unsigned int k2 = 0; k2 < k; k2++)
    797       {
    798         const struct ANASTASIS_Policy *p2 = policies[k2];
    799         for (unsigned int l2 = 0; l2 < p2->truths_length; l2++)
    800           if (0 ==
    801               GNUNET_memcmp (&pt->uuid,
    802                              &p2->truths[l2]->uuid))
    803           {
    804             unique = false;
    805             break;
    806           }
    807         if (! unique)
    808           break;
    809       }
    810       if (! unique)
    811         continue;
    812 
    813       GNUNET_assert (0 ==
    814                      json_array_append_new (
    815                        esc_methods,
    816                        GNUNET_JSON_PACK (
    817                          GNUNET_JSON_pack_data_auto ("uuid",
    818                                                      &pt->uuid),
    819                          GNUNET_JSON_pack_string ("url",
    820                                                   pt->url),
    821                          GNUNET_JSON_pack_string ("instructions",
    822                                                   pt->instructions),
    823                          GNUNET_JSON_pack_data_auto ("truth_key",
    824                                                      &pt->truth_key),
    825                          GNUNET_JSON_pack_data_auto ("question_salt",
    826                                                      &pt->question_salt),
    827                          GNUNET_JSON_pack_data_auto ("provider_salt",
    828                                                      &pt->provider_salt),
    829                          GNUNET_JSON_pack_string ("escrow_type",
    830                                                   pt->type))));
    831     }
    832   }
    833 
    834   {
    835     json_t *recovery_document;
    836     size_t rd_size;
    837     char *rd_str;
    838     Bytef *cbuf;
    839     uLongf cbuf_size;
    840     int ret;
    841     uint32_t be_size;
    842 
    843     recovery_document = GNUNET_JSON_PACK (
    844       GNUNET_JSON_pack_allow_null (
    845         GNUNET_JSON_pack_string ("secret_name",
    846                                  secret_name)),
    847       GNUNET_JSON_pack_array_steal ("policies",
    848                                     dec_policies),
    849       GNUNET_JSON_pack_array_steal ("escrow_methods",
    850                                     esc_methods),
    851       GNUNET_JSON_pack_data_varsize ("encrypted_core_secret",
    852                                      cser->enc_core_secret,
    853                                      cser->enc_core_secret_size));
    854     GNUNET_assert (NULL != recovery_document);
    855     ANASTASIS_CRYPTO_destroy_encrypted_core_secret (cser);
    856     cser = NULL;
    857 
    858     rd_str = json_dumps (recovery_document,
    859                          JSON_COMPACT | JSON_SORT_KEYS);
    860     GNUNET_assert (NULL != rd_str);
    861     json_decref (recovery_document);
    862     rd_size = strlen (rd_str);
    863     cbuf_size = compressBound (rd_size);
    864     be_size = htonl ((uint32_t) rd_size);
    865     cbuf = GNUNET_malloc (cbuf_size + sizeof (uint32_t));
    866     memcpy (cbuf,
    867             &be_size,
    868             sizeof (uint32_t));
    869     ret = compress (cbuf + sizeof (uint32_t),
    870                     &cbuf_size,
    871                     (const Bytef *) rd_str,
    872                     rd_size);
    873     if (Z_OK != ret)
    874     {
    875       /* compression failed!? */
    876       GNUNET_break (0);
    877       free (rd_str);
    878       GNUNET_free (cbuf);
    879       ANASTASIS_secret_share_cancel (ss);
    880       return NULL;
    881     }
    882     free (rd_str);
    883     recovery_document_size = (size_t) (cbuf_size + sizeof (uint32_t));
    884     recovery_document_str = (char *) cbuf;
    885   }
    886 
    887   meta_size = sizeof (struct GNUNET_HashCode);
    888   if (NULL != secret_name)
    889     meta_size += strlen (secret_name) + 1;
    890   meta = GNUNET_malloc (meta_size);
    891   GNUNET_CRYPTO_hash (recovery_document_str,
    892                       recovery_document_size,
    893                       (struct GNUNET_HashCode *) meta);
    894   if (NULL != secret_name)
    895     memcpy (meta + sizeof (struct GNUNET_HashCode),
    896             secret_name,
    897             strlen (secret_name) + 1);
    898 
    899   for (unsigned int l = 0; l < ss->pss_length; l++)
    900   {
    901     struct PolicyStoreState *pss = &ss->pss[l];
    902     void *recovery_data;
    903     size_t recovery_data_size;
    904     struct ANASTASIS_CRYPTO_AccountPrivateKeyP anastasis_priv;
    905     size_t enc_meta_size = 0;
    906     void *enc_meta = NULL;
    907 
    908     pss->ss = ss;
    909     pss->anastasis_url = GNUNET_strdup (providers[l].provider_url);
    910     pss->provider_salt = providers[l].provider_salt;
    911     pss->payment_secret = providers[l].payment_secret;
    912     ANASTASIS_CRYPTO_user_identifier_derive (id_data,
    913                                              &pss->provider_salt,
    914                                              &pss->id);
    915     ANASTASIS_CRYPTO_recovery_metadata_encrypt (&pss->id,
    916                                                 meta,
    917                                                 meta_size,
    918                                                 &enc_meta,
    919                                                 &enc_meta_size);
    920     ANASTASIS_CRYPTO_account_private_key_derive (&pss->id,
    921                                                  &anastasis_priv);
    922     ANASTASIS_CRYPTO_recovery_document_encrypt (&pss->id,
    923                                                 recovery_document_str,
    924                                                 recovery_document_size,
    925                                                 &recovery_data,
    926                                                 &recovery_data_size);
    927     GNUNET_CRYPTO_hash (recovery_data,
    928                         recovery_data_size,
    929                         &pss->curr_hash);
    930     pss->pso = ANASTASIS_policy_store (
    931       ss->ctx,
    932       pss->anastasis_url,
    933       &anastasis_priv,
    934       recovery_data,
    935       recovery_data_size,
    936       enc_meta,
    937       enc_meta_size,
    938       payment_years_requested,
    939       (! GNUNET_is_zero (&pss->payment_secret))
    940       ? &pss->payment_secret
    941       : NULL,
    942       pay_timeout,
    943       &policy_store_cb,
    944       pss);
    945     GNUNET_free (recovery_data);
    946     GNUNET_free (enc_meta);
    947     if (NULL == pss->pso)
    948     {
    949       GNUNET_break (0);
    950       ANASTASIS_secret_share_cancel (ss);
    951       GNUNET_free (recovery_document_str);
    952       GNUNET_free (meta);
    953       return NULL;
    954     }
    955   }
    956   GNUNET_free (meta);
    957   GNUNET_free (recovery_document_str);
    958   return ss;
    959 }
    960 
    961 
    962 void
    963 ANASTASIS_secret_share_cancel (struct ANASTASIS_SecretShare *ss)
    964 {
    965   for (unsigned int i = 0; i<ss->pss_length; i++)
    966   {
    967     struct PolicyStoreState *pssi = &ss->pss[i];
    968 
    969     if (NULL != pssi->pso)
    970     {
    971       ANASTASIS_policy_store_cancel (pssi->pso);
    972       pssi->pso = NULL;
    973     }
    974     GNUNET_free (pssi->anastasis_url);
    975     GNUNET_free (pssi->payment_request);
    976   }
    977   GNUNET_free (ss->pss);
    978   GNUNET_free (ss);
    979 }