gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-anastasis] branch master updated: split into recovery and backup


From: gnunet
Subject: [taler-anastasis] branch master updated: split into recovery and backup
Date: Fri, 05 Feb 2021 11:38:42 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new c84456d  split into recovery and backup
c84456d is described below

commit c84456d9177d2b5a3636dfdc1dc2c9524c4e9b5b
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Fri Feb 5 11:38:40 2021 +0100

    split into recovery and backup
---
 src/lib/Makefile.am          |    3 +-
 src/lib/anastasis.c          | 2270 ------------------------------------------
 src/lib/anastasis_recovery.c | 1059 ++++++++++++++++++++
 3 files changed, 1061 insertions(+), 2271 deletions(-)

diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index ec92c34..654f615 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -13,7 +13,8 @@ libanastasis_la_LDFLAGS = \
   -version-info 0:0:0 \
   -no-undefined
 libanastasis_la_SOURCES = \
-  anastasis.c
+  anastasis_backup.c \
+  anastasis_recovery.c
 libanastasis_la_LIBADD = \
   $(top_builddir)/src/util/libanastasisutil.la \
   $(top_builddir)/src/restclient/libanastasisrest.la \
diff --git a/src/lib/anastasis.c b/src/lib/anastasis.c
deleted file mode 100644
index e7db6c1..0000000
--- a/src/lib/anastasis.c
+++ /dev/null
@@ -1,2270 +0,0 @@
-/*
-  This file is part of Anastasis
-  Copyright (C) 2020 Taler Systems SA
-
-  Anastasis is free software; you can redistribute it and/or modify it under 
the
-  terms of the GNU Lesser General Public License as published by the Free 
Software
-  Foundation; either version 3, or (at your option) any later version.
-
-  Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
-  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License along with
-  Anastasis; see the file COPYING.GPL.  If not, see 
<http://www.gnu.org/licenses/>
-*/
-/**
- * @brief anastasis client api
- * @author Christian Grothoff
- * @author Dominik Meister
- * @author Dennis Neufeld
- */
-
-#include "anastasis.h"
-#include <taler/taler_json_lib.h>
-#include <gnunet/gnunet_util_lib.h>
-#include <taler/taler_merchant_service.h>
-
-
-/**
- * stores provider URLs, identity key material, decrypted recovery document 
(internally!)
-*/
-struct ANASTASIS_Recovery
-{
-  /**
-   * Callback to send back a recovery document with the policies and the 
version
-   */
-  ANASTASIS_PolicyCallback pc;
-
-  /**
-   * closure for the Policy callback
-   */
-  void *pc_cls;
-
-  /**
-   * Callback to send back the core secret which was saved by
-   * anastasis, after all challenges are completed
-  */
-  ANASTASIS_CoreSecretCallback csc;
-
-  /**
-   * Closure for the core secret callback
-   */
-  void *csc_cls;
-
-  /**
-   * Identity key material used for the derivation of keys
-   */
-  struct ANASTASIS_CRYPTO_UserIdentifierP id;
-
-  /**
-   * Public key for a request
-   */
-  struct ANASTASIS_CRYPTO_AccountPublicKeyP pub_key;
-
-  /**
-   * Curl context
-   */
-  struct GNUNET_CURL_Context *ctx;
-
-  /**
-   * Reference to the policy lookup operation which is executed
-   */
-  struct ANASTASIS_PolicyLookupOperation *plo;
-
-  /**
-   * Encrypted recovery document, only used for the description
-   */
-  void *encrypted_recovery_document;
-
-  /**
-   * size of the ecrypted recovery document
-   */
-  size_t enc_rec_doc_size;
-
-  /**
-   * expected http status
-   */
-  unsigned int http_status;
-
-  /**
-   * expected http status
-   */
-  unsigned int response_code;
-
-  /**
-   * retrieved encrypted core secret from policy
-   */
-  void *enc_core_secret;
-
-  /**
-   * size of the core secret
-   */
-  size_t enc_core_secret_size;
-
-  /**
-   * Length of available decryption policies //FIXME: Copy paste?
-   */
-  struct ANASTASIS_CRYPTO_PowSalt policy_salt;
-
-  /**
-   * Length of available decryption policies //FIXME: Copy paste?
-   */
-  struct ANASTASIS_Challenge *solved_challenges;
-
-  /**
-   * Length of available decryption policies //FIXME: Copy paste?
-   */
-  unsigned int solved_challenge_pos;
-
-  /**
-   * Recovery information which is sent to the user
-   */
-  struct ANASTASIS_RecoveryInformation *ri;
-
-  /**
-   * Identity data to user id from.
-   */
-  const json_t *id_data;
-};
-
-
-/**
- * Challenge struct contains the nonce and public key's needed for the
- * recovery process and a reference to ANASTASIS_Recovery.
- */
-struct ANASTASIS_Challenge
-{
-  /**
-   * Callback which gives back the instructions and a status code of the 
request to the user
-   */
-  ANASTASIS_ChallengeCallback cc;
-
-  /**
-   * Closure for the challenge callback
-   */
-  void *cc_cls;
-
-  /**
-   * Callback which gives back the instructions and a status code of the 
request to the user
-   */
-  ANASTASIS_AnswerFeedback af;
-
-  /**
-   * Closure for the challenge callback
-   */
-  void *af_cls;
-
-  /**
-   * Reference to the recovery process which is ongoing
-   */
-  struct ANASTASIS_Recovery *recovery;
-
-  /**
-   * url to the escrow provider for this challenge
-   */
-  const char *url;
-
-  /**
-   * truth public key which identifies this challenge
-   */
-  struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
-
-  /**
-   * nonce which identifies the challenge
-   */
-  struct ANASTASIS_CRYPTO_NonceP nonce;
-
-  /**
-   * Key used to encrypt the truth passed to the server
-   */
-  struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
-
-  /**
-   * Salt used to encrypt the truth
-   */
-  struct ANASTASIS_CRYPTO_PowSalt truth_salt;
-
-  /**
-   * plaintext challenge which is sent to the client
-   */
-  void *challenge;
-
-  /**
-   * size of the challenge
-   */
-  size_t challenge_size;
-
-  /**
-   * method of the challenge
-   */
-  const char *escrow_method;
-
-  /**
-   * keyshare lookup operation
-   */
-  struct ANASTASIS_KeyShareLookupOperation *kslo;
-
-  /**
-   * Curl context
-   */
-  struct GNUNET_CURL_Context *ctx;
-
-  /**
-   * Encrypted key share
-   */
-  struct ANASTASIS_CRYPTO_KeyShareP *key_share;
-
-  /**
-   * Status of the challenge 0 pending, 1 solved
-   */
-  unsigned int solved;
-
-  /**
-   * Expected http status
-   */
-  unsigned int http_status;
-
-  /**
-   * Challenge instructions
-   */
-  const char *instructions;
-
-  /**
-   * Cost for authentication
-   */
-  struct TALER_Amount cost;
-
-  /**
-   * Passes back the payment information for the current challenge
-   */
-  ANASTASIS_ChallengePaymentCallback cpc;
-
-  /**
-   * Closure for the payment callback
-   */
-  void *cpc_cls;
-
-  /**
-   * The /truth GET operation handle.
-   */
-  struct ANASTASIS_ChallengeRunOperation *cro;
-
-  /**
-   * Sends back the status and the instructions of the challenge start
-   */
-  ANASTASIS_ChallengeStartCallback csc;
-
-  /**
-   * Closure for the Challenge Start
-   */
-  void *csc_cls;
-
-  /**
-   * Payment identifier.
-   */
-  struct ANASTASIS_PaymentSecretP payment_secret;
-
-  /**
-   * Payment order ID we got back, if any. Otherwise NULL.
-   */
-  char *payment_order_id;
-
-  /**
-   * Payment order ID we are to provide in the request, may be NULL.
-   */
-  const char *payment_order_req;
-
-  bool payment_requested;
-};
-
-
-struct ANASTASIS_ChallengeAnswerOperation
-{
-  struct ANASTASIS_Challenge *c;
-};
-
-
-/**
- * Function called with the results of a #ANASTASIS_keyshare_lookup().
- *
- * @param cls closure
- * @param http_status HTTP status of the request
- * @param ud details about the lookup operation
- */
-static void
-keyshare_lookup_cb (void *cls,
-                    unsigned int http_status,
-                    const struct ANASTASIS_KeyShareDownloadDetails *dd)
-{
-  struct ANASTASIS_Challenge *c = cls;
-  c->kslo = NULL;
-  if (http_status != c->http_status)
-  {
-    c->af (c->af_cls,
-           http_status,
-           TALER_EC_INVALID); // FIXME: Error Code
-    return;
-  }
-  struct ANASTASIS_CRYPTO_UserIdentifierP id;
-  ANASTASIS_CRYPTO_user_identifier_derive (c->recovery->id_data,
-                                           &c->truth_salt,
-                                           &id);
-  ANASTASIS_CRYPTO_keyshare_decrypt (dd->encrypted_key_share,
-                                     &id,
-                                     &c->key_share);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d decrypted keyshare is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (&c->key_share),
-              (unsigned long long) sizeof (c->key_share));
-
-  c->recovery->solved_challenges[c->recovery->solved_challenge_pos] = *c;
-  c->recovery->solved_challenge_pos++;
-  c->af (c->af_cls,
-         http_status,
-         TALER_EC_NONE);
-
-  /**
-   * 0 equals the challenge was not solved 1 it was solved
-   */
-  bool missing = true;
-  /**
-   * Index of the policy which was completed
-   */
-  unsigned int success = UINT_MAX;
-
-  for (unsigned int i = 0; i < c->recovery->ri->dps_len; i++)
-  {
-    for (unsigned int j = 0; j < c->recovery->ri->dps[i].nonces_length; j++)
-    {
-      missing = true;
-      for (unsigned int k = 0; k < c->recovery->solved_challenge_pos; k++)
-      {
-        if (0 == memcmp (&c->recovery->ri->dps[i].nonces[j],
-                         &c->recovery->solved_challenges[k].nonce,
-                         sizeof(struct ANASTASIS_CRYPTO_NonceP)))
-        {
-          missing = false;
-          break;
-        }
-      }
-      if (missing == true)
-      {
-        break;
-      }
-    }
-    if (missing == false)
-    {
-      success = i;
-      break;
-    }
-  }
-
-  if (success != UINT_MAX)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d policy was solved \n", __FILE__, __LINE__);
-    void *core_secret;
-    size_t core_secret_size;
-    struct ANASTASIS_CRYPTO_KeyShareP
-      key_shares[c->recovery->ri->dps[success].nonces_length];
-    struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
-    for (unsigned int l = 0; l < c->recovery->ri->dps[success].nonces_length;
-         l++)
-    {
-      for (unsigned int m = 0; m < c->recovery->solved_challenge_pos; m++)
-      {
-        if (0 == memcmp (&c->recovery->ri->dps[success].nonces[l],
-                         &c->recovery->solved_challenges[m].nonce,
-                         sizeof(struct ANASTASIS_CRYPTO_NonceP)))
-        {
-          key_shares[l] = *c->recovery->solved_challenges[m].key_share;
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "At %s:%d keyshare added %s-%llu b at position %x\n",
-                      __FILE__, __LINE__,
-                      TALER_B2S (&key_shares[l]),
-                      (unsigned long long) sizeof (c->key_share),
-                      l);
-        }
-      }
-    }
-    ANASTASIS_CRYPTO_policy_key_derive (key_shares,
-                                        c->recovery->ri->dps[success].
-                                        nonces_length,
-                                        &c->recovery->ri->dps[success].salt,
-                                        &policy_key);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d the policy key is %s-%llu b\n", __FILE__, __LINE__,
-                TALER_B2S (&policy_key),
-                (unsigned long long) sizeof (policy_key));
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
-                __LINE__,
-                TALER_b2s (c->recovery->enc_core_secret,
-                           c->recovery->enc_core_secret_size),
-                (unsigned long long) c->recovery->enc_core_secret_size);
-
-    ANASTASIS_CRYPTO_core_secret_recover (&c->recovery->ri->dps[success].emk,
-                                          policy_key,
-                                          c->recovery->enc_core_secret,
-                                          c->recovery->enc_core_secret_size,
-                                          &core_secret,
-                                          &core_secret_size);
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d decrypted core secret is %s-%llu b\n", __FILE__,
-                __LINE__,
-                TALER_b2s (core_secret,
-                           core_secret_size),
-                (unsigned long long) core_secret_size);
-    c->recovery->csc (c->recovery->csc_cls,
-                      core_secret,
-                      core_secret_size);
-  }
-}
-
-
-/**
- * Cancel a challenge answer operation.
- *
- * @param pso the challenge answer operation to cancel
- */
-void
-ANASTASIS_challenge_answer_cancel (struct
-                                   ANASTASIS_ChallengeAnswerOperation *cao)
-{
-  if (NULL != cao->c)
-  {
-    GNUNET_free (cao->c);
-  }
-  GNUNET_free (cao);
-}
-
-
-struct ANASTASIS_ChallengeAnswerOperation *
-ANASTASIS_challenge_answer (struct GNUNET_CURL_Context *ctx,
-                            struct ANASTASIS_Challenge *c,
-                            const char *answer_str,
-                            ANASTASIS_AnswerFeedback af,
-                            void *af_cls)
-{
-  struct ANASTASIS_ChallengeAnswerOperation *cao;
-
-  cao = GNUNET_new (struct ANASTASIS_ChallengeAnswerOperation);
-  cao->c = c;
-  c->af = af;
-  c->ctx = ctx;
-  c->af_cls = af_cls;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d challenge answer is %s\n", __FILE__, __LINE__,
-              answer_str);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d challenge %s-%llu is solved with url %s \n", __FILE__,
-              __LINE__,
-              TALER_B2S (&c->truth_public_key),
-              (unsigned long long) sizeof (c->truth_public_key),
-              c->url);
-
-  c->http_status = MHD_HTTP_OK;
-  if (0 == strcmp (c->escrow_method,
-                   "question"))
-  {
-    struct GNUNET_HashCode hashed_answer;
-    char *str;
-
-    GNUNET_CRYPTO_hash (answer_str,
-                        strlen (answer_str),
-                        &hashed_answer);
-    str = GNUNET_STRINGS_data_to_string_alloc (&hashed_answer,
-                                               sizeof (hashed_answer));
-    c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
-                                         c->url,
-                                         &c->truth_public_key,
-                                         &c->truth_key,
-                                         c->payment_requested,
-                                         &c->payment_secret,
-                                         str,
-                                         &keyshare_lookup_cb,
-                                         c);
-    GNUNET_free (str);
-    if (NULL == c->kslo)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-  }
-  else
-  {
-    c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
-                                         c->url,
-                                         &c->truth_public_key,
-                                         &c->truth_key,
-                                         c->payment_requested,
-                                         &c->payment_secret,
-                                         answer_str,
-                                         &keyshare_lookup_cb,
-                                         c);
-    if (NULL == c->kslo)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-  }
-  return cao;
-}
-
-
-struct ANASTASIS_ChallengeInformation *
-ANASTASIS_get_challenge (struct ANASTASIS_Challenge *challenge)
-{
-  struct ANASTASIS_ChallengeInformation *ci;
-
-  ci = GNUNET_new (struct ANASTASIS_ChallengeInformation);
-  ci->truth_public_key = &challenge->truth_public_key;
-  ci->method = challenge->escrow_method;
-  ci->url = challenge->url;
-  ci->nonce = &challenge->nonce;
-  ci->instructions = challenge->instructions;
-  ci->solved = challenge->solved;
-  ci->challenge = challenge;
-
-  return ci;
-}
-
-
-struct ANASTASIS_Challenge *
-ANASTASIS_json_to_challenge (json_t *challenge)
-{
-  GNUNET_assert (json_is_object (challenge));
-  const char *challenge_str;
-  struct ANASTASIS_Challenge *c = NULL;
-
-  challenge_str =
-    json_string_value (
-      json_object_get (challenge,
-                       "challenge"));
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_STRINGS_string_to_data (
-                   challenge_str,
-                   strlen (challenge_str),
-                   c,
-                   sizeof (struct ANASTASIS_Challenge)));
-  return c;
-}
-
-
-json_t *
-ANASTASIS_challenge_information_to_json (const struct
-                                         ANASTASIS_ChallengeInformation *ci)
-{
-  return json_pack ("{s:o,s:s,s:s,s:o,s:s:s:I,s:o}",
-                    "truth_public_key",
-                    GNUNET_JSON_from_data_auto (ci->truth_public_key),
-                    "method",
-                    ci->method,
-                    "url",
-                    ci->url,
-                    "nonce",
-                    GNUNET_JSON_from_data_auto (ci->nonce),
-                    "instructions",
-                    ci->instructions,
-                    "solved",
-                    (json_int_t) ci->solved,
-                    "challenge",
-                    GNUNET_JSON_from_data_auto (ci->challenge));
-}
-
-
-/**
- * Function called with the results of a #ANASTASIS_challenge_run().
- *
- * @param cls closure
- * @param http_status HTTP status of the request
- * @param response_string payment request or instructions
- */
-static void
-challenge_run_cb (void *cls,
-                  unsigned int http_status,
-                  char *response_string)
-{
-  struct ANASTASIS_Challenge *c = cls;
-  c->cro = NULL;
-
-  if (http_status == MHD_HTTP_PAYMENT_REQUIRED)
-  {
-    const char *m;
-
-    if (0 != strncmp (response_string,
-                      "taler://pay/http",
-                      strlen ("taler://pay/http")))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Did not find `%s' in `%s'\n",
-                  "/-/-/",
-                  response_string);
-      /*FIXME ERROR*/
-      return;
-    }
-    m = strstr (response_string, "/-/-/");
-    if (NULL == m)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Did not find `%s' in `%s'\n",
-                  "/-/-/",
-                  response_string);
-      /*FIXME ERROR*/
-
-      /* NOTE: The above is a simplifying assumption for the
-         test-logic, hitting this code merely means that
-         the assumptions for the test (i.e. no instance) are
-         not satisfied, it is not inherently the case that
-         the above token must appear in the payment request!
-
-         So if you hit this, you might just want to modify
-         the code here to handle this better! */
-      return;
-    }
-    c->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
-    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                "Order ID from Anastasis service is `%s'\n",
-                c->payment_order_id);
-    c->cpc (c->cpc_cls,
-            response_string,
-            c->url,
-            http_status);
-    return;
-  }
-  c->csc (c->csc_cls,
-          response_string,
-          http_status);
-  return;
-}
-
-
-void
-ANASTASIS_challenge_start (struct GNUNET_CURL_Context *ctx,
-                           struct ANASTASIS_Challenge *c,
-                           ANASTASIS_ChallengePaymentCallback cpc,
-                           void *cpc_cls,
-                           ANASTASIS_ChallengeStartCallback csc,
-                           void *csc_cls)
-{
-  c->ctx = ctx;
-  c->csc = csc;
-  c->csc_cls = csc_cls;
-  c->cpc = cpc;
-  c->cpc_cls = cpc_cls;
-  c->payment_requested = false;
-
-  if (c->payment_order_id != NULL)
-  {
-    GNUNET_STRINGS_string_to_data (c->payment_order_id,
-                                   strlen (c->payment_order_id),
-                                   &c->payment_secret,
-                                   sizeof (struct
-                                           ANASTASIS_PaymentSecretP));
-    c->payment_requested = true;
-  }
-
-  c->cro = ANASTASIS_challenge_run (c->ctx,
-                                    c->url,
-                                    &c->truth_public_key,
-                                    &c->truth_key,
-                                    c->payment_requested
-                                    ? &c->payment_secret
-                                    : NULL,
-                                    c->payment_requested,
-                                    &challenge_run_cb,
-                                    c);
-  if (NULL == c->cro)
-  {
-    GNUNET_break (0);
-    return;
-  }
-}
-
-
-/**
- * Function called with the results of a ANASTASIS_policy_lookup
- *
- * @param cls closure
- * @param http_status HTTP status of the request
- * @param ud details about the lookup operation
- */
-static void
-policy_lookup_cb (void *cls,
-                  unsigned int http_status,
-                  const struct ANASTASIS_DownloadDetails *dd)
-{
-  struct ANASTASIS_Recovery *r = cls;
-  void *plaintext;
-  size_t size_plaintext;
-  json_t *recovery_document;
-  json_error_t json_error;
-  json_t *dec_policies;
-  json_t *esc_methods;
-
-  r->response_code = http_status;
-  r->ri = GNUNET_new (struct ANASTASIS_RecoveryInformation);
-  r->plo = NULL;
-  if (http_status != r->http_status)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unexpected response code %u in %s:%u\n",
-                http_status,
-                __FILE__,
-                __LINE__);
-
-    r->pc (r->pc_cls,
-           r->ri,
-           TALER_EC_INVALID); // FIXME: Error Code
-    // r->pc = NULL;
-    ANASTASIS_recovery_abort (r);
-    return;
-  }
-  if (NULL == dd->policy)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No recovery data available");
-    r->pc (r->pc_cls,
-           r->ri,
-           TALER_EC_INVALID); // FIXME: Error Code
-    // r->pc = NULL;
-    ANASTASIS_recovery_abort (r);
-    return;
-  }
-  ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id,
-                                              dd->policy,
-                                              dd->policy_size,
-                                              &plaintext,
-                                              &size_plaintext);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d rec doc after enc is %s \n",
-              __FILE__, __LINE__,
-              TALER_b2s (plaintext, size_plaintext));
-  // FIXME COMPRESSION
-
-  recovery_document = json_loadb ((char *) plaintext,
-                                  size_plaintext,
-                                  JSON_DECODE_ANY,
-                                  &json_error);
-  GNUNET_free (plaintext);
-  if (NULL == recovery_document)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to read JSON input: %s at %d:%s (offset: %d)\n",
-                json_error.text,
-                json_error.line,
-                json_error.source,
-                json_error.position);
-    GNUNET_break_op (0);
-    r->pc (r->pc_cls,
-           r->ri,
-           TALER_EC_INVALID); // FIXME: Error Code
-    ANASTASIS_recovery_abort (r);
-    return;
-  }
-
-  struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_json ("policies",
-                           &dec_policies),
-    GNUNET_JSON_spec_json ("escrow_methods",
-                           &esc_methods),
-    GNUNET_JSON_spec_varsize ("core_secret",
-                              &r->enc_core_secret,
-                              &r->enc_core_secret_size),
-    GNUNET_JSON_spec_end ()
-  };
-
-  if (GNUNET_OK !=
-      GNUNET_JSON_parse (recovery_document,
-                         spec,
-                         NULL, NULL))
-  {
-    GNUNET_break_op (0);
-    json_decref (recovery_document);
-    recovery_document = NULL;
-    GNUNET_JSON_parse_free (spec);
-    r->pc (r->pc_cls,
-           r->ri,
-           TALER_EC_INVALID); // FIXME: Error Code
-    ANASTASIS_recovery_abort (r);
-    return;
-  }
-  json_decref (recovery_document);
-  recovery_document = NULL;
-  r->ri->cs_len = json_array_size (esc_methods);
-  r->ri->dps_len = json_array_size (dec_policies);
-  r->ri->dps = GNUNET_new_array (r->ri->dps_len,
-                                 struct ANASTASIS_DecryptionPolicy);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
-              __LINE__,
-              TALER_b2s (r->enc_core_secret,
-                         r->enc_core_secret_size),
-              (unsigned long long) r->enc_core_secret_size);
-  r->solved_challenges = GNUNET_new_array (r->ri->cs_len,
-                                           struct ANASTASIS_Challenge);
-
-  struct ANASTASIS_Challenge **cs = GNUNET_new_array (r->ri->cs_len,
-                                                      struct 
ANASTASIS_Challenge
-                                                      *);
-  for (unsigned int i = 0; i < r->ri->cs_len; i++)
-  {
-    cs[i] = GNUNET_new (struct ANASTASIS_Challenge);
-    struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_fixed_auto ("nonce",
-                                   &cs[i]->nonce),
-      GNUNET_JSON_spec_string ("url",
-                               &cs[i]->url),
-      GNUNET_JSON_spec_string ("instructions",
-                               &cs[i]->instructions),
-      GNUNET_JSON_spec_fixed_auto ("truth_key",
-                                   &cs[i]->truth_key),
-      GNUNET_JSON_spec_fixed_auto ("salt",
-                                   &cs[i]->truth_salt),
-      GNUNET_JSON_spec_string ("escrow_method",
-                               &cs[i]->escrow_method),
-      GNUNET_JSON_spec_end ()
-    };
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (json_array_get (esc_methods, i),
-                           spec,
-                           NULL, NULL))
-    {
-      GNUNET_break_op (0);
-      json_decref (esc_methods);
-      GNUNET_JSON_parse_free (spec);
-      r->pc (r->pc_cls,
-             r->ri,
-             TALER_EC_INVALID); // FIXME: Error Code
-      ANASTASIS_recovery_abort (r);
-      return;
-    }
-    ANASTASIS_CRYPTO_truth_public_key_derive (&cs[i]->nonce,
-                                              &cs[i]->truth_public_key);
-    cs[i]->recovery = r;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d challenge public key is %s-%llu b\n", __FILE__,
-                __LINE__,
-                TALER_B2S (&cs[i]->truth_public_key),
-                (unsigned long long) sizeof (cs[i]->truth_public_key));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d url is %s\n", __FILE__, __LINE__,
-                cs[i]->url);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d truth key is %s-%llu b\n", __FILE__, __LINE__,
-                TALER_B2S (&cs[i]->truth_key),
-                (unsigned long long) sizeof (cs[i]->truth_key));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d truth_salt is %s-%llu b\n", __FILE__, __LINE__,
-                TALER_B2S (&cs[i]->truth_salt),
-                (unsigned long long) sizeof (cs[i]->truth_salt));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d escrow method is %s\n", __FILE__, __LINE__,
-                cs[i]->escrow_method);
-  }
-
-  for (unsigned int j = 0; j < r->ri->dps_len; j++)
-  {
-    size_t n_index;
-    json_t *nonces;
-    json_t *nonce;
-
-    struct GNUNET_JSON_Specification spec[] = {
-      GNUNET_JSON_spec_fixed_auto ("master_key",
-                                   &r->ri->dps[j].emk),
-      GNUNET_JSON_spec_fixed_auto ("salt",
-                                   &r->ri->dps[j].salt),
-      GNUNET_JSON_spec_uint32 ("nonces_length",
-                               &r->ri->dps[j].nonces_length),
-      GNUNET_JSON_spec_end ()
-    };
-    nonces = json_object_get (json_array_get (dec_policies, j),
-                              "nonces");
-    GNUNET_assert (json_is_array (nonces));
-
-    if (GNUNET_OK !=
-        GNUNET_JSON_parse (json_array_get (dec_policies, j),
-                           spec,
-                           NULL, NULL))
-    {
-      GNUNET_break_op (0);
-      GNUNET_JSON_parse_free (spec);
-      json_decref (dec_policies);
-      r->pc (r->pc_cls,
-             r->ri,
-             TALER_EC_INVALID); // FIXME: Error Code
-      ANASTASIS_recovery_abort (r);
-      return;
-    }
-
-    r->ri->dps[j].nonces = GNUNET_new_array (r->ri->dps[j].nonces_length,
-                                             struct ANASTASIS_CRYPTO_NonceP);
-
-    json_array_foreach (nonces, n_index, nonce)
-    {
-      const char *nonce_str = json_string_value (nonce);
-      GNUNET_STRINGS_string_to_data (nonce_str,
-                                     strlen (nonce_str),
-                                     &r->ri->dps[j].nonces[n_index],
-                                     sizeof (struct ANASTASIS_CRYPTO_NonceP));
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d escrow nonce is %s-%llu b\n",
-                  __FILE__, __LINE__,
-                  TALER_B2S (&r->ri->dps[j].nonces[n_index]),
-                  (unsigned long long) sizeof (r->ri->dps[j].nonces[n_index]));
-    }
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d encrypted master key is %s-%llu b\n",
-                __FILE__,  __LINE__,
-                TALER_B2S (&r->ri->dps[j].emk),
-                (unsigned long long) sizeof (r->ri->dps[j].emk));
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d policy salt is %s-%llu b\n",
-                __FILE__, __LINE__,
-                TALER_B2S (&r->ri->dps[j].salt),
-                (unsigned long long) sizeof (r->ri->dps[j].salt));
-  }
-  r->solved_challenge_pos = 0;
-  r->ri->cs = cs;
-  // SETUP POLICY CALLBACK
-  if (NULL != r->pc)
-  {
-    r->pc (r->pc_cls,
-           r->ri,
-           TALER_EC_NONE); // FIXME: Error Code
-    // r->pc = NULL;
-  }
-  json_decref (esc_methods);
-  json_decref (dec_policies);
-}
-
-
-/**
-* Starts the recovery process by opening callbacks for the coresecret and a 
policy callback. A list of
-* providers is checked for policies and passed back to the client.
-*
-* @param ctx the CURL context used to connect to the backend
-* @param id_data contains the users identity, (user account on providers)
-* @param version defines the version which will be downloaded NULL for latest 
version
-* @param anastasis_provider_url NULL terminated list of possible provider urls
-* @param salt the server salt
-* @param pc opens the policy call back which holds the downloaded version and 
the policies
-* @param pc_cls closure for callback
-* @param csc core secret callback is opened, with this the core secert is 
passed to the client after the authentication
-* @param csc_cls handle for the callback
-*/
-struct ANASTASIS_Recovery *
-ANASTASIS_recovery_begin (struct GNUNET_CURL_Context *ctx,
-                          const json_t *id_data,
-                          unsigned int version,
-                          const char *anastasis_provider_url,
-                          const struct ANASTASIS_CRYPTO_PowSalt *salt,
-                          ANASTASIS_PolicyCallback pc,
-                          void *pc_cls,
-                          ANASTASIS_CoreSecretCallback csc,
-                          void *csc_cls)
-{
-  struct ANASTASIS_Recovery *r;
-
-  r = GNUNET_new (struct ANASTASIS_Recovery);
-  r->csc = csc;
-  r->csc_cls = csc_cls;
-  r->pc = pc;
-  r->pc_cls = pc_cls;
-  r->ctx = ctx;
-  r->id_data = id_data;
-  r->http_status = MHD_HTTP_OK;
-  ANASTASIS_CRYPTO_user_identifier_derive (id_data,
-                                           salt,
-                                           &r->id);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d user_identfier is %s-%llu b\n",
-              __FILE__, __LINE__,
-              TALER_B2S (&r->id),
-              (unsigned long long) sizeof (r->id));
-  ANASTASIS_CRYPTO_account_public_key_derive (&r->id,
-                                              &r->pub_key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d public key is %s-%llu b\n",
-              __FILE__, __LINE__,
-              TALER_B2S (&r->pub_key),
-              (unsigned long long) sizeof (r->pub_key));
-
-  if (version != 0)
-  {
-    r->plo = ANASTASIS_policy_lookup_version (r->ctx,
-                                              anastasis_provider_url,
-                                              &r->pub_key,
-                                              &policy_lookup_cb,
-                                              r,
-                                              &version);
-    if (NULL == r->plo)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-  }
-  else
-  {
-    r->plo = ANASTASIS_policy_lookup (r->ctx,
-                                      anastasis_provider_url,
-                                      &r->pub_key,
-                                      &policy_lookup_cb,
-                                      r);
-    if (NULL == r->plo)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-  }
-
-  return r;
-}
-
-
-void
-ANASTASIS_recovery_free (struct ANASTASIS_Recovery *r)
-{
-  GNUNET_free (r->solved_challenges);
-  GNUNET_free (r->encrypted_recovery_document);
-  GNUNET_free (r->ri->dps);
-  GNUNET_free (r->ri->cs);
-  GNUNET_free (r->ri);
-  GNUNET_free (r);
-}
-
-
-/**
-* Cancels the recovery process
-* @param r handle to the recovery struct
-*/
-void
-ANASTASIS_recovery_abort (struct ANASTASIS_Recovery *r)
-{
-  if (NULL != r->plo)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "policy lookup aborted");
-    ANASTASIS_policy_lookup_cancel (r->plo);
-    r->plo = NULL;
-  }
-  ANASTASIS_recovery_free (r);
-}
-
-
-/* Upload api
------------------------------------------------------------------ */
-/**
-* provider_url + nonce
-*/
-struct ANASTASIS_Truth
-{
-  /**
-   * url to the server
-   */
-  const char *url;
-
-  /**
-   * identification of the truth
-   */
-  struct ANASTASIS_CRYPTO_NonceP nonce;
-
-  /**
-   * method used for this truth
-   */
-  const char *method;
-
-  /**
-   * method used for this truth
-   */
-  const char *instructions;
-
-  /**
-   * mime type of the truth
-   */
-  const char *mime_type;
-
-  /**
-   * keyshare of this truth, used to generate policy keys
-   */
-  struct ANASTASIS_CRYPTO_KeyShareP key_share;
-
-  /**
-   * key used to encrypt this truth
-   */
-  struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
-
-  /**
-   * server salt used to derive user identifier
-   */
-  struct ANASTASIS_CRYPTO_PowSalt salt;
-};
-
-/**
-* Truth Upload struct
-*/
-struct ANASTASIS_TruthUpload
-{
-  /**
-   * Expected HTTP Status
-   */
-  unsigned int http_status;
-
-  /**
-   * CURL Context for the Post Request
-   */
-  struct GNUNET_CURL_Context *ctx;
-
-  /**
-   * User identifier used for the keyshare encryption
-   */
-  struct ANASTASIS_CRYPTO_UserIdentifierP id;
-
-  /**
-   * Callback which tells the user the payment details for the upload
-   */
-  ANASTASIS_TruthPaymentCallback tpc;
-
-  /**
-   * Closure for the payment callback
-   */
-  void *tpc_cls;
-
-  /**
-   * Callback which sends back the generated truth object later used to build 
the policy
-   */
-  ANASTASIS_TruthCallback tc;
-
-  /**
-   * Closure for the Callback
-   */
-  void *tc_cls;
-
-  /**
-   * Reference to the Truthstore Operation
-   */
-  struct ANASTASIS_TruthStoreOperation *tso;
-
-  // FIXME: Implement payment for truth upload/keyshare download
-  int payment_requested;
-
-  const char *paid_order_id;
-};
-
-
-static void
-truth_store_callback (void *cls,
-                      enum ANASTASIS_ErrorCode ec,
-                      unsigned int http_status,
-                      const struct ANASTASIS_UploadDetails *ud)
-{
-  struct ANASTASIS_TruthUpload *tu = cls;
-  tu->tso = NULL;
-
-  if (NULL != ud)
-  {
-    switch (ud->us)
-    {
-    case ANASTASIS_US_SUCCESS:
-      break;
-    case ANASTASIS_US_PAYMENT_REQUIRED:
-      {
-        struct TALER_MERCHANT_PayUriData pd;
-
-        if (GNUNET_OK !=
-            TALER_MERCHANT_parse_pay_uri (ud->details.payment_request,
-                                          &pd))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Did not find `%s' in `%s'\n",
-                      "/-/-/",
-                      ud->details.payment_request);
-          GNUNET_break (0);
-          return;
-        }
-        tu->paid_order_id = GNUNET_strdup (pd.order_id);
-        TALER_MERCHANT_parse_pay_uri_free (&pd);
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "At %s:%d Order ID from Anastasis service is %s\n",
-                    __FILE__, __LINE__,
-                    tu->paid_order_id);
-      }
-      break;
-    case ANASTASIS_US_CONFLICTING_TRUTH:
-      {
-        GNUNET_break (0);
-        return;
-      }
-    case ANASTASIS_US_HTTP_ERROR:
-      break;
-    case ANASTASIS_US_CLIENT_ERROR:
-      GNUNET_break (0);
-      return;
-    case ANASTASIS_US_SERVER_ERROR:
-      GNUNET_break (0);
-      return;
-    default:
-      GNUNET_break (0);
-      return;
-    }
-  }
-  return;
-}
-
-
-/**
-* Uploads a truth object onto a escrow provider
-*
-* @param ctx the CURL context used to connect to the backend
-* @param user_id user identifier derived from user data and backend salt
-* @param method defines the method of the challenge (secure question, sms, 
email)
-* @param instructions depending on method! usually only for security 
question/answer!
-* @param mime_type format of the challenge
-* @param salt the server salt
-* @param truth_data contains the truth for this challenge i.e. phone number, 
email address
-* @param truth_data_size size of the data
-* @param tpc opens a truth payment callback to pay the upload
-* @param tpc_cls closure for the payment callback
-* @param tc opens the truth callback which contains the status of the upload
-* @param tc_cls closure for the callback
-*/
-struct ANASTASIS_TruthUpload *
-ANASTASIS_truth_upload (struct GNUNET_CURL_Context *ctx,
-                        const struct ANASTASIS_CRYPTO_UserIdentifierP *user_id,
-                        const char *provider_url,
-                        const char *method,
-                        const char *instructions,
-                        const char *mime_type,
-                        const struct ANASTASIS_CRYPTO_PowSalt *salt,
-                        const void *truth_data,
-                        size_t truth_data_size,
-                        ANASTASIS_TruthPaymentCallback tpc,
-                        void *tpc_cls,
-                        ANASTASIS_TruthCallback tc,
-                        void *tc_cls)
-{
-  // FIXME Challenge
-  struct ANASTASIS_TruthUpload *tu;
-  struct ANASTASIS_Truth *t;
-  // struct SaltState *ss; FIXME unused
-  struct ANASTASIS_CRYPTO_EncryptedKeyShareP *encrypted_key_share;
-  struct ANASTASIS_CRYPTO_TruthPublicKeyP pub_key;
-  void *encrypted_truth;
-  size_t encrypted_truth_size;
-  json_t *truth;
-
-  GNUNET_assert (NULL != user_id);
-  GNUNET_assert (NULL != salt);
-
-  tu = GNUNET_new (struct ANASTASIS_TruthUpload);
-  t = GNUNET_new (struct ANASTASIS_Truth);
-  tu->tc_cls = tc_cls;
-  tu->tpc_cls = tpc_cls;
-  tu->tpc = tpc;
-  tu->tc = tc;
-  tu->ctx = ctx;
-  tu->id = *user_id;
-  t->url = provider_url;
-  t->method = method;
-  t->instructions = instructions;
-  t->mime_type = mime_type;
-  t->salt = *salt;
-
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
-                              &t->nonce,
-                              sizeof (struct ANASTASIS_CRYPTO_NonceP));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d nonce is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (&t->nonce),
-              (unsigned long long) sizeof (t->nonce));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d server salt is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (salt),
-              (unsigned long long) sizeof (*salt));
-  ANASTASIS_CRYPTO_keyshare_create (&t->key_share);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d keyshare is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (&t->key_share),
-              (unsigned long long) sizeof (t->key_share));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d user identifier is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (&tu->id),
-              (unsigned long long) sizeof (tu->id));
-  ANASTASIS_CRYPTO_keyshare_encrypt (&t->key_share,
-                                     &tu->id,
-                                     &encrypted_key_share);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d encrypted key share is %s-%llu b\n", __FILE__, 
__LINE__,
-              TALER_B2S (encrypted_key_share),
-              (unsigned long long) sizeof (*encrypted_key_share));
-
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
-                              &t->truth_key,
-                              sizeof (struct ANASTASIS_CRYPTO_TruthKeyP));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d truth key is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (&t->truth_key),
-              (unsigned long long) sizeof (t->truth_key));
-
-  struct GNUNET_HashCode hashed_answer;
-  GNUNET_CRYPTO_hash (truth_data,
-                      truth_data_size,
-                      &hashed_answer);
-
-  ANASTASIS_CRYPTO_truth_encrypt (&t->truth_key,
-                                  &hashed_answer,
-                                  sizeof(hashed_answer),
-                                  &encrypted_truth,
-                                  &encrypted_truth_size);
-
-  truth = json_pack ("{s:o," /* encrypted KeyShare */
-                     " s:s," /* method */
-                     " s:o," /* nonce */
-                     " s:s}", /* truth_mime */
-                     "keyshare_data", GNUNET_JSON_from_data_auto (
-                       encrypted_key_share),
-                     "method", method,
-                     "encrypted_truth", GNUNET_JSON_from_data (
-                       encrypted_truth, encrypted_truth_size),
-                     "truth_mime", mime_type);
-  GNUNET_free (encrypted_key_share);
-  GNUNET_free (encrypted_truth);
-  if (NULL == truth)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  ANASTASIS_CRYPTO_truth_public_key_derive (&t->nonce,
-                                            &pub_key);
-  tu->tc = tc;
-  tu->tc_cls = tc_cls;
-  tu->tso = ANASTASIS_truth_store (tu->ctx,
-                                   t->url,
-                                   &pub_key,
-                                   truth,
-                                   tu->payment_requested,
-                                   tu->paid_order_id,
-                                   &truth_store_callback,
-                                   tu);
-  if (NULL == tu->tso)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  if (NULL != tu->tc)
-  {
-    tu->tc (tu->tc_cls,
-            t);
-    tu->tc = NULL;
-  }
-
-  // FIXME PAYMENT CALLBACK
-  return tu;
-}
-
-
-/**
-* Cancels a upload process
-* @param tu handle for the upload
-*/
-void
-ANASTASIS_truth_upload_cancel (struct ANASTASIS_TruthUpload *tu)
-{
-  if (NULL != tu->tso)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "truth lookup aborted \n");
-    ANASTASIS_truth_store_cancel (tu->tso);
-    tu->tso = NULL;
-  }
-  GNUNET_free (tu);
-}
-
-
-/**
-* Free's the truth object which was allocated
-* @param t object to clean up
-*/
-void
-ANASTASIS_truth_free (struct ANASTASIS_Truth *t)
-{
-  GNUNET_free (t);
-}
-
-
-json_t *
-ANASTASIS_truth_to_json (const struct ANASTASIS_Truth *t)
-{
-  return json_pack ("{s:s,s:o,s:s,s:s,s:s,s:o,s:o,s:o}",
-                    "url",
-                    t->url,
-                    "nonce",
-                    GNUNET_JSON_from_data_auto (&t->nonce),
-                    "method",
-                    t->method,
-                    "instructions",
-                    t->instructions,
-                    "mime-type",
-                    t->mime_type,
-                    "key-share",
-                    GNUNET_JSON_from_data_auto (&t->key_share),
-                    "truth-key",
-                    GNUNET_JSON_from_data_auto (&t->truth_key),
-                    "salt",
-                    GNUNET_JSON_from_data_auto (&t->salt));
-}
-
-
-struct ANASTASIS_Truth *
-ANASTASIS_truth_from_json (const json_t *json)
-{
-  struct ANASTASIS_Truth *t = GNUNET_new (struct ANASTASIS_Truth);
-  struct GNUNET_JSON_Specification spec[] = {
-    GNUNET_JSON_spec_string ("url",
-                             &t->url),
-    GNUNET_JSON_spec_fixed_auto ("nonce",
-                                 &t->nonce),
-    GNUNET_JSON_spec_string ("method",
-                             &t->method),
-    GNUNET_JSON_spec_string ("instructions",
-                             &t->instructions),
-    GNUNET_JSON_spec_string ("mime-type",
-                             &t->mime_type),
-    GNUNET_JSON_spec_fixed_auto ("key-share",
-                                 &t->key_share),
-    GNUNET_JSON_spec_fixed_auto ("truth-key",
-                                 &t->truth_key),
-    GNUNET_JSON_spec_fixed_auto ("salt",
-                                 &t->salt),
-    GNUNET_JSON_spec_end ()
-  };
-  const char *err_name;
-  unsigned int err_line;
-
-  if (GNUNET_OK !=
-      GNUNET_JSON_parse (json,
-                         spec,
-                         &err_name,
-                         &err_line))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to parse truth in line %u (%s)\n",
-                err_line,
-                err_name);
-    return NULL;
-  }
-  return t;
-}
-
-
-/**
-* Policy object to upload
-*/
-struct ANASTASIS_Policy
-{
-  /**
-  * Encrypted policy master key
-  */
-  struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
-
-  /**
-   * salt used to encrypt the master key
-   */
-  struct ANASTASIS_CRYPTO_SaltP salt;
-
-  /**
-   * set of truths inside this policy
-   */
-  struct ANASTASIS_CRYPTO_NonceP *nonces;
-
-  /**
-   * length of methods used
-   */
-  uint32_t nonces_length;
-
-  /**
-   * array of truths
-   */
-  const struct ANASTASIS_Truth **truths;
-};
-
-/**
-* Creates a policy with a set of trutht's
-* Creates the policy key with the different key shares from the truths and 
encrypts the escrow master key.
-* @param truths array of truths which are stored on different providers
-* @param truths_len amount of truths in this policy
-*/
-struct ANASTASIS_Policy *
-ANASTASIS_policy_create (const struct ANASTASIS_Truth *truths[],
-                         unsigned int truths_len)
-{
-  struct ANASTASIS_Policy *p;
-  const struct ANASTASIS_Truth *truth;
-  struct ANASTASIS_CRYPTO_KeyShareP key_shares[truths_len];
-  struct ANASTASIS_CRYPTO_NonceP nonces[truths_len];
-
-  p = GNUNET_new (struct ANASTASIS_Policy);
-
-  GNUNET_assert (NULL != *truths);
-  GNUNET_assert (truths_len > 0);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d truth array length is %i\n", __FILE__, __LINE__,
-              truths_len);
-
-  for (unsigned int i = 0; i < truths_len; i++)
-  {
-    truth = truths[i];
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d truth is %s-%llu b\n", __FILE__, __LINE__,
-                TALER_B2S (truth),
-                (unsigned long long) sizeof (struct ANASTASIS_Truth));
-    GNUNET_memcpy (&key_shares[i],
-                   &truth->key_share,
-                   sizeof (struct ANASTASIS_CRYPTO_KeyShareP));
-    GNUNET_assert (NULL != &key_shares[i]);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d keyshare is %s-%llu b\n", __FILE__, __LINE__,
-                TALER_B2S (&key_shares[i]),
-                (unsigned long long) sizeof (key_shares[i]));
-    GNUNET_memcpy (&nonces[i],
-                   &truth->nonce,
-                   sizeof(struct ANASTASIS_CRYPTO_NonceP));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d nonce is %s-%llu b\n", __FILE__, __LINE__,
-                TALER_B2S (&nonces[i]),
-                (unsigned long long) sizeof (nonces[i]));
-  }
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
-                              &p->salt,
-                              sizeof (struct ANASTASIS_CRYPTO_SaltP));
-  ANASTASIS_CRYPTO_policy_key_derive (key_shares,
-                                      truths_len,
-                                      &p->salt,
-                                      &p->policy_key);
-  GNUNET_assert (NULL != &p->policy_key);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d policy key is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (&p->policy_key),
-              (unsigned long long) sizeof (p->policy_key));
-  p->truths = GNUNET_malloc (truths_len * sizeof (struct ANASTASIS_Truth *));
-  GNUNET_memcpy (p->truths,
-                 truths,
-                 truths_len * sizeof (struct ANASTASIS_Truth *));
-  p->nonces = GNUNET_malloc (truths_len * sizeof (struct
-                                                  ANASTASIS_CRYPTO_NonceP));
-  GNUNET_memcpy (p->nonces,
-                 nonces,
-                 truths_len * sizeof (struct ANASTASIS_CRYPTO_NonceP));
-  p->nonces_length = truths_len;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d policy is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_B2S (p),
-              (unsigned long long) sizeof (*p));
-  return p;
-}
-
-
-/**
-* Destroys a policy object
-* @param p handle for the policy to destroy
-*/
-void
-ANASTASIS_policy_destroy (struct ANASTASIS_Policy *p)
-{
-  if (NULL != p->nonces)
-  {
-    GNUNET_free (p->nonces);
-  }
-  if (NULL != p->truths)
-  {
-    GNUNET_free (p->truths);
-  }
-
-  GNUNET_free (p);
-}
-
-
-struct ANASTASIS_SecretShare;
-
-/**
- * State for a "policy store" CMD.
- */
-struct PolicyStoreState
-{
-  /**
-   * User identifier used as entropy source for the account public key
-   */
-  struct ANASTASIS_CRYPTO_UserIdentifierP id;
-
-  /**
-   * Struct to obtain the salt from the server
-   */
-  struct SaltState *st;
-
-  /**
-   * The policy data.
-   */
-  void *recovery_data;
-
-  /**
-   * Number of bytes in @e recovery_data
-   */
-  size_t recovery_data_size;
-
-  /**
-   * Expected status code.
-   */
-  unsigned int http_status;
-
-  /**
-   * Server salt
-   */
-  const struct ANASTASIS_CRYPTO_PowSalt *server_salt;
-
-  /**
-   * Status of the transaction
-   */
-  enum ANASTASIS_ErrorCode ec;
-
-  /**
-   * Eddsa Publickey.
-   */
-  struct ANASTASIS_CRYPTO_AccountPublicKeyP anastasis_pub;
-
-  /**
-   * Eddsa Privatekey.
-   */
-  struct ANASTASIS_CRYPTO_AccountPrivateKeyP anastasis_priv;
-
-  /**
-   * Hash of the previous upload (maybe bogus if
-   * #ANASTASIS_TESTING_UO_PREV_HASH_WRONG is set in @e uo).
-   * Maybe all zeros if there was no previous upload.
-   */
-  struct GNUNET_HashCode prev_hash;
-
-  /**
-   * Hash of the current upload.
-   */
-  struct GNUNET_HashCode curr_hash;
-
-  /**
-   * The /policy POST operation handle.
-   */
-  struct ANASTASIS_PolicyStoreOperation *pso;
-
-  /**
-   * URL of the anastasis backend.
-   */
-  const char *anastasis_url;
-
-  /**
-   * Payment identifier.
-   */
-  struct ANASTASIS_PaymentSecretP payment_secret;
-
-  /**
-   * Payment order ID we got back, if any. Otherwise NULL.
-   */
-  char *payment_order_id;
-
-  /**
-   * Payment order ID we are to provide in the request, may be NULL.
-   */
-  const char *payment_order_req;
-
-  int payment_requested;
-
-  /**
-   * Previous upload, or NULL for none. Used to calculate what THIS
-   * upload is based on.
-   */
-  const char *prev_upload;
-
-  /**
-   * reference to SecretShare
-   */
-  struct ANASTASIS_SecretShare *ss;
-
-  /**
-   * Callback which gives back the payment details
-   */
-  ANASTASIS_SharePaymentCallback spc;
-
-  /**
-   * Closure for the payment callback
-   */
-  void *spc_cls;
-
-  /**
-   * Callback which gives back the result of the POST Request
-   */
-  ANASTASIS_ShareResultCallback src;
-
-  /**
-   * Closure for the Result Callback
-   */
-  void *src_cls;
-};
-
-/**
-* Defines a recovery document upload process (recovery document consists of 
multiple policies)
-*/
-struct ANASTASIS_SecretShare
-{
-  /**
-   * Closure for the Result Callback
-   */
-  struct GNUNET_CURL_Context *ctx;
-
-  /**
-   * References for the upload states and operations (size of truths passed)
-   */
-  struct PolicyStoreState **pss;
-
-  /**
-   * Closure for the Result Callback
-   */
-  unsigned int pss_length;
-};
-
-
-/**
- * Free the state of a "policy store" CMD, and possibly
- * cancel it if it did not complete.
- *
- * @param cls closure.
- */
-static void
-policy_store_cleanup (void *cls)
-{
-  struct PolicyStoreState *pss = cls;
-
-  if (NULL != pss->pso)
-  {
-    ANASTASIS_policy_store_cancel (pss->pso);
-    pss->pso = NULL;
-  }
-  if (NULL != pss->recovery_data)
-    GNUNET_free (pss->recovery_data);
-  if (NULL != pss->payment_order_id)
-    GNUNET_free (pss->payment_order_id);
-  GNUNET_free (pss);
-}
-
-
-static void
-policy_store_cb (void *cls,
-                 enum ANASTASIS_ErrorCode ec,
-                 unsigned int http_status,
-                 const struct ANASTASIS_UploadDetails *ud)
-{
-  struct PolicyStoreState *pss = cls;
-  pss->pso = NULL;
-  pss->ec = ec;
-  if ((http_status != pss->http_status) &&
-      (http_status != MHD_HTTP_PAYMENT_REQUIRED))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unexpected response code %u/%d in %s:%u\n",
-                http_status,
-                (int) ec,
-                __FILE__,
-                __LINE__);
-
-    if (NULL != pss->src)
-    {
-      pss->src (pss->src_cls,
-                &pss->curr_hash,
-                pss->anastasis_url,
-                ec,
-                http_status);
-      pss->src = NULL;
-    }
-    return;
-  }
-  if (NULL != ud)
-  {
-    switch (ud->us)
-    {
-    case ANASTASIS_US_SUCCESS:
-      if (0 != GNUNET_memcmp (&pss->curr_hash,
-                              ud->details.curr_backup_hash))
-      {
-        GNUNET_break (0);
-        return;
-      }
-      break;
-    case ANASTASIS_US_PAYMENT_REQUIRED:
-      {
-        struct TALER_MERCHANT_PayUriData pd;
-
-        if (GNUNET_OK !=
-            TALER_MERCHANT_parse_pay_uri (ud->details.payment_request,
-                                          &pd))
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Did not find `%s' in `%s'\n",
-                      "/-/-/",
-                      ud->details.payment_request);
-          GNUNET_break (0);
-          return;
-        }
-        pss->payment_order_id = GNUNET_strdup (pd.order_id);
-        TALER_MERCHANT_parse_pay_uri_free (&pd);
-        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "At %s:%d Order ID from Anastasis service is %s\n",
-                    __FILE__, __LINE__,
-                    pss->payment_order_id);
-        memset (&pss->curr_hash,
-                0,
-                sizeof (struct GNUNET_HashCode));
-        if (NULL != pss->spc)
-        {
-          pss->spc (pss->spc_cls,
-                    ud->details.payment_request,
-                    pss->anastasis_url,
-                    ec);
-          pss->spc = NULL;
-          return;
-        }
-      }
-    case ANASTASIS_US_CONFLICTING_POLICY:
-      GNUNET_break (0);
-      return;
-    case ANASTASIS_US_HTTP_ERROR:
-      break;
-    case ANASTASIS_US_CLIENT_ERROR:
-      GNUNET_break (0);
-      return;
-    case ANASTASIS_US_SERVER_ERROR:
-      GNUNET_break (0);
-      return;
-    default:
-      GNUNET_break (0);
-      return;
-    }
-    if (NULL != pss->src)
-    {
-      pss->src (pss->src_cls,
-                &pss->curr_hash,
-                pss->anastasis_url,
-                ec,
-                http_status);
-      pss->src = NULL;
-      return;
-    }
-  }
-  GNUNET_break (0);
-}
-
-
-/**
- * Counts the number of different providers
- *
- * @param policies Array of policies
- * @param policies_len Length of array
- * @return number of different providers
- */
-static unsigned int
-ANASTASIS_get_num_urls (const struct ANASTASIS_Policy *policies[],
-                        unsigned int policies_len)
-{
-  unsigned int len = 0;
-  unsigned int unique_urls_len = 0;
-
-  for (unsigned int i = 0; i < policies_len; i++)
-  {
-    len += policies[i]->nonces_length;
-  }
-
-  {
-    char *provider[len];
-
-    for (unsigned int l = 0; l < policies_len; l++)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d policy is %s-%llu b\n", __FILE__, __LINE__,
-                  TALER_B2S (policies[l]),
-                  (unsigned long long) sizeof (struct ANASTASIS_Policy));
-
-      for (unsigned int j = 0; j < policies[l]->nonces_length; j++)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "At %s:%d truth is %s-%llu b\n", __FILE__, __LINE__,
-                    TALER_B2S (policies[l]->truths[j]),
-                    (unsigned long long) sizeof (struct ANASTASIS_Truth));
-
-        int contains_url = 0;
-        if (0 < unique_urls_len)
-        {
-          for (unsigned int k = 0; k < unique_urls_len; k++)
-          {
-            GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                        "At %s:%d provider url from truth is %s\n", __FILE__,
-                        __LINE__,
-                        policies[l]->truths[j]->url);
-
-            if (NULL != provider[k])
-            {
-              if (0 ==
-                  strcmp (policies[l]->truths[j]->url, provider[k]))
-              {
-                contains_url = 1;
-                break;
-              }
-            }
-          }
-        }
-
-        if (0 == contains_url)
-        {
-          provider[unique_urls_len] = GNUNET_malloc (sizeof (char)
-                                                     * strlen (
-                                                       policies[l]->truths[j]->
-                                                       url) + 1);
-          strcpy (provider[unique_urls_len], policies[l]->truths[j]->url);
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "At %s:%d unique provider url is %s\n", __FILE__,
-                      __LINE__,
-                      provider[unique_urls_len]);
-          unique_urls_len++;
-        }
-      }
-    }
-    for (unsigned int i = 0; i < unique_urls_len; i++)
-    {
-      GNUNET_free (provider[i]);
-    }
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d unique_urls_len is %d\n", __FILE__, __LINE__,
-              unique_urls_len);
-
-  return unique_urls_len;
-}
-
-
-struct ANASTASIS_SecretShare *
-ANASTASIS_secret_share (struct GNUNET_CURL_Context *ctx,
-                        const json_t *id_data,
-                        const struct GNUNET_HashCode *last_etag,
-                        const struct ANASTASIS_Policy *policies[],
-                        unsigned int policies_len,
-                        const struct ANASTASIS_PaymentDetails *pds,
-                        unsigned int pds_len,
-                        ANASTASIS_SharePaymentCallback spc,
-                        void *spc_cls,
-                        ANASTASIS_ShareResultCallback src,
-                        void *src_cls,
-                        const void *core_secret,
-                        size_t core_secret_size)
-{
-  struct ANASTASIS_SecretShare *ss;
-
-  GNUNET_assert (policies_len > 0);
-  unsigned int pss_length = ANASTASIS_get_num_urls (policies,
-                                                    policies_len);
-  struct PolicyStoreState *pss[pss_length];
-  struct ANASTASIS_CRYPTO_EncryptedMasterKeyP
-    encrypted_master_keys[policies_len];
-  struct ANASTASIS_CRYPTO_PolicyKeyP policy_keys[policies_len];
-  void *encrypted_core_secret;
-  // Recovery document contains the array decryption policies and the array 
escrow methods
-  json_t *recovery_document;
-  size_t recovery_document_size;
-  char *recovery_document_str;
-  // json array
-  json_t *dec_policies;
-  // json array
-  json_t *esc_methods;
-
-  if (0 == pss_length)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "At %s:%d pss_length is %d!\n", __FILE__, __LINE__,
-                pss_length);
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  ss = GNUNET_new (struct ANASTASIS_SecretShare);
-  for (unsigned int i = 0; i < pss_length; i++)
-  {
-    pss[i] = GNUNET_new (struct PolicyStoreState);
-    pss[i]->ss = ss;
-  }
-  ss->pss = pss;
-  ss->pss_length = pss_length;
-  ss->ctx = ctx;
-
-  for (unsigned int i = 0; i < policies_len; i++)
-  {
-    policy_keys[i] = policies[i]->policy_key;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d core secret is %s-%llu b\n", __FILE__, __LINE__,
-              TALER_b2s (core_secret,
-                         core_secret_size),
-              (unsigned long long) core_secret_size);
-
-  ANASTASIS_CRYPTO_core_secret_encrypt (policy_keys,
-                                        policies_len,
-                                        core_secret,
-                                        core_secret_size,
-                                        &encrypted_core_secret,
-                                        encrypted_master_keys);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
-              __LINE__,
-              TALER_b2s (encrypted_core_secret,
-                         core_secret_size),
-              (unsigned long long) core_secret_size);
-
-  dec_policies = json_array ();
-  esc_methods = json_array ();
-  int index_pss = 0;
-  for (unsigned int k = 0; k < policies_len; k++)
-  {
-    const struct ANASTASIS_Policy *policy = policies[k];
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d policy is %s\n",
-                __FILE__,
-                __LINE__,
-                TALER_B2S (&policy->policy_key));
-
-    json_t *nonces = json_array ();
-    for (unsigned int b = 0; b < policy->nonces_length; b++)
-    {
-      json_array_append (nonces,
-                         GNUNET_JSON_from_data_auto (&policy->nonces[b]));
-    }
-
-    if (0 !=
-        json_array_append_new (
-          dec_policies,
-          json_pack ("{s:o,"   /* encrypted master key */
-                     " s:o,"   /* policy nonces  */
-                     " s:o,"   /* policy salt  */
-                     " s:i}",  /* policy nonces length */
-                     "master_key",
-                     GNUNET_JSON_from_data_auto (
-                       &encrypted_master_keys[k]),
-                     "nonces",
-                     nonces,
-                     "salt",
-                     GNUNET_JSON_from_data_auto (&policy->salt),
-                     "nonces_length",
-                     (int) policy->nonces_length)))
-    {
-      GNUNET_break (0);
-      json_decref (dec_policies);
-      return NULL;
-    }
-
-    // FIXME CHALLENGE
-    for (unsigned int l = 0; l < policy->nonces_length; l++)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d truth is %s-%llu b\n", __FILE__, __LINE__,
-                  TALER_B2S (policy->truths[l]),
-                  (unsigned long long) sizeof (struct ANASTASIS_Truth));
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d keyshare is %s-%llu b\n", __FILE__, __LINE__,
-                  TALER_B2S (&policy->truths[l]->key_share),
-                  (unsigned long
-                   long) sizeof (policy->truths[l]->key_share));
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d truthkey is %s-%llu b\n", __FILE__, __LINE__,
-                  TALER_B2S (&policy->truths[l]->truth_key),
-                  (unsigned long
-                   long) sizeof (policy->truths[l]->truth_key));
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d nonce is %s-%llu b\n", __FILE__, __LINE__,
-                  TALER_B2S (&policy->truths[l]->nonce),
-                  (unsigned long long) sizeof (policy->truths[l]->nonce));
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d server salt is %s-%llu b\n", __FILE__, __LINE__,
-                  TALER_B2S (&policy->truths[l]->salt),
-                  (unsigned long long) sizeof (policy->truths[l]->salt));
-
-      // FIXME: JUST APPEND UNIQUE NONCES!!!
-      // creates a json array for saving
-      if (0 !=
-          json_array_append_new (
-            esc_methods,
-            json_pack ("{s:o," /* truth nonce */
-                       " s:s," /* provider url */
-                       " s:s," /* instructions */
-                       " s:o," /* truth key */
-                       " s:o," /* truth salt */
-                       " s:s}", /* escrow method */
-                       "nonce",
-                       GNUNET_JSON_from_data_auto (
-                         &policy->truths[l]->nonce),
-                       "url",
-                       policy->truths[l]->url,
-                       "instructions",
-                       policy->truths[l]->instructions,
-                       "truth_key", GNUNET_JSON_from_data_auto (
-                         &policy->truths[l]->truth_key),
-                       "salt", GNUNET_JSON_from_data_auto (
-                         &policy->truths[l]->salt),
-                       "escrow_method",
-                       policy->truths[l]->method)))
-      {
-        GNUNET_break (0);
-        json_decref (esc_methods);
-        return NULL;
-      }
-
-      // prepares policy store operation
-      bool contains_url = false;
-      for (unsigned int j = 0; j < ss->pss_length; j++)
-      {
-        if (NULL != ss->pss[j]->anastasis_url)
-        {
-          if (0 == strcmp (ss->pss[j]->anastasis_url,
-                           policy->truths[l]->url))
-          {
-            contains_url = true;
-            break;
-          }
-        }
-      }
-      if (! contains_url)
-      {
-        ss->pss[index_pss]->anastasis_url = policy->truths[l]->url;
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "At %s:%d anastasis url is %s\n", __FILE__, __LINE__,
-                    ss->pss[index_pss]->anastasis_url);
-        if (NULL != last_etag)
-          ss->pss[index_pss]->prev_hash = *last_etag;
-        ss->pss[index_pss]->server_salt = &policy->truths[l]->salt;
-        if (pds_len > 0)
-        {
-          for (unsigned int m = 0; 0 < pds_len; m++)
-          {
-            if (NULL == pds[m].provider_url)
-              continue;
-            if (0 == strcmp (pds[m].provider_url,
-                             policy->truths[l]->url))
-            {
-              ss->pss[index_pss]->payment_secret
-                = pds[m].payment_secret;
-              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                          "At %s:%d Payment-Identifier from PD is: %s\n",
-                          __FILE__,
-                          __LINE__,
-                          TALER_B2S (&pds[m].payment_secret));
-              break;
-            }
-          }
-        }
-        index_pss++;
-      }
-    }
-  }
-
-  recovery_document = json_pack (
-    "{s:o," /* decryption policies */
-    " s:o," /* escrow methods */
-    " s:o}", /* encrypted core secret */
-    "policies", dec_policies,
-    "escrow_methods", esc_methods,
-    "core_secret", GNUNET_JSON_from_data (encrypted_core_secret,
-                                          core_secret_size));
-  GNUNET_free (encrypted_core_secret);
-  GNUNET_assert (NULL != recovery_document);
-
-  // FIXME COMPRESSION
-  recovery_document_str = json_dumps (recovery_document,
-                                      JSON_COMPACT | JSON_SORT_KEYS);
-  recovery_document_size = strlen (recovery_document_str);
-  GNUNET_assert (NULL != recovery_document_str);
-  json_decref (recovery_document);
-
-  for (unsigned int l = 0; l < ss->pss_length; l++)
-  {
-    ss->pss[l]->http_status = MHD_HTTP_NO_CONTENT;
-
-    ss->pss[l]->spc = spc;
-    ss->pss[l]->spc_cls = spc_cls;
-    ss->pss[l]->src = src;
-    ss->pss[l]->src_cls = src_cls;
-
-    ANASTASIS_CRYPTO_user_identifier_derive (id_data,
-                                             ss->pss[l]->server_salt,
-                                             &ss->pss[l]->id);
-
-    ANASTASIS_CRYPTO_account_private_key_derive (&ss->pss[l]->id,
-                                                 &ss->pss[l]->anastasis_priv);
-
-    ANASTASIS_CRYPTO_recovery_document_encrypt (&ss->pss[l]->id,
-                                                recovery_document_str,
-                                                recovery_document_size,
-                                                &ss->pss[l]->recovery_data,
-                                                
&ss->pss[l]->recovery_data_size);
-    GNUNET_free (recovery_document_str);
-    // hash recovery data
-    GNUNET_CRYPTO_hash (ss->pss[l]->recovery_data,
-                        ss->pss[l]->recovery_data_size,
-                        &ss->pss[l]->curr_hash);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d current hash is %s-%llu b\n", __FILE__, __LINE__,
-                TALER_B2S (&ss->pss[l]->curr_hash),
-                (unsigned long long) sizeof (struct GNUNET_HashCode));
-
-    ss->pss[l]->pso = ANASTASIS_policy_store (ss->ctx,
-                                              ss->pss[l]->anastasis_url,
-                                              &ss->pss[l]->anastasis_priv,
-                                              ( ( (NULL !=
-                                                   ss->pss[l]->prev_upload) &&
-                                                  (GNUNET_NO == GNUNET_is_zero 
(
-                                                     last_etag)) ))
-                                              ? last_etag
-                                              : NULL,
-                                              ss->pss[l]->recovery_data,
-                                              ss->pss[l]->recovery_data_size,
-                                              ss->pss[l]->payment_requested,
-                                              (pds_len > 0)
-                                              ? &ss->pss[l]->payment_secret
-                                              : NULL,
-                                              &policy_store_cb,
-                                              ss->pss[l]);
-    if (NULL == ss->pss[l]->pso)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-  }
-  return ss;
-}
-
-
-/**
-* Cancels a secret share request
-* @param ss handle to the request
-*/
-void
-ANASTASIS_secret_share_cancel (struct ANASTASIS_SecretShare *ss)
-{
-  GNUNET_free (ss);
-}
diff --git a/src/lib/anastasis_recovery.c b/src/lib/anastasis_recovery.c
new file mode 100644
index 0000000..73cf85d
--- /dev/null
+++ b/src/lib/anastasis_recovery.c
@@ -0,0 +1,1059 @@
+/*
+  This file is part of Anastasis
+  Copyright (C) 2020 Taler Systems SA
+
+  Anastasis is free software; you can redistribute it and/or modify it under 
the
+  terms of the GNU Lesser General Public License as published by the Free 
Software
+  Foundation; either version 3, or (at your option) any later version.
+
+  Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
+  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  Anastasis; see the file COPYING.GPL.  If not, see 
<http://www.gnu.org/licenses/>
+*/
+/**
+ * @brief anastasis client api
+ * @author Christian Grothoff
+ * @author Dominik Meister
+ * @author Dennis Neufeld
+ */
+
+#include "anastasis.h"
+#include <taler/taler_json_lib.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_merchant_service.h>
+
+
+/**
+ * stores provider URLs, identity key material, decrypted recovery document 
(internally!)
+*/
+struct ANASTASIS_Recovery
+{
+  /**
+   * Callback to send back a recovery document with the policies and the 
version
+   */
+  ANASTASIS_PolicyCallback pc;
+
+  /**
+   * closure for the Policy callback
+   */
+  void *pc_cls;
+
+  /**
+   * Callback to send back the core secret which was saved by
+   * anastasis, after all challenges are completed
+  */
+  ANASTASIS_CoreSecretCallback csc;
+
+  /**
+   * Closure for the core secret callback
+   */
+  void *csc_cls;
+
+  /**
+   * Identity key material used for the derivation of keys
+   */
+  struct ANASTASIS_CRYPTO_UserIdentifierP id;
+
+  /**
+   * Public key for a request
+   */
+  struct ANASTASIS_CRYPTO_AccountPublicKeyP pub_key;
+
+  /**
+   * Curl context
+   */
+  struct GNUNET_CURL_Context *ctx;
+
+  /**
+   * Reference to the policy lookup operation which is executed
+   */
+  struct ANASTASIS_PolicyLookupOperation *plo;
+
+  /**
+   * Encrypted recovery document, only used for the description
+   */
+  void *encrypted_recovery_document;
+
+  /**
+   * size of the ecrypted recovery document
+   */
+  size_t enc_rec_doc_size;
+
+  /**
+   * expected http status
+   */
+  unsigned int http_status;
+
+  /**
+   * expected http status
+   */
+  unsigned int response_code;
+
+  /**
+   * retrieved encrypted core secret from policy
+   */
+  void *enc_core_secret;
+
+  /**
+   * size of the core secret
+   */
+  size_t enc_core_secret_size;
+
+  /**
+   * Length of available decryption policies //FIXME: Copy paste?
+   */
+  struct ANASTASIS_CRYPTO_PowSalt policy_salt;
+
+  /**
+   * Length of available decryption policies //FIXME: Copy paste?
+   */
+  struct ANASTASIS_Challenge *solved_challenges;
+
+  /**
+   * Length of available decryption policies //FIXME: Copy paste?
+   */
+  unsigned int solved_challenge_pos;
+
+  /**
+   * Recovery information which is sent to the user
+   */
+  struct ANASTASIS_RecoveryInformation *ri;
+
+  /**
+   * Identity data to user id from.
+   */
+  const json_t *id_data;
+};
+
+
+/**
+ * Challenge struct contains the nonce and public key's needed for the
+ * recovery process and a reference to ANASTASIS_Recovery.
+ */
+struct ANASTASIS_Challenge
+{
+  /**
+   * Callback which gives back the instructions and a status code of the 
request to the user
+   */
+  ANASTASIS_ChallengeCallback cc;
+
+  /**
+   * Closure for the challenge callback
+   */
+  void *cc_cls;
+
+  /**
+   * Callback which gives back the instructions and a status code of the 
request to the user
+   */
+  ANASTASIS_AnswerFeedback af;
+
+  /**
+   * Closure for the challenge callback
+   */
+  void *af_cls;
+
+  /**
+   * Reference to the recovery process which is ongoing
+   */
+  struct ANASTASIS_Recovery *recovery;
+
+  /**
+   * url to the escrow provider for this challenge
+   */
+  const char *url;
+
+  /**
+   * truth public key which identifies this challenge
+   */
+  struct ANASTASIS_CRYPTO_TruthPublicKeyP truth_public_key;
+
+  /**
+   * nonce which identifies the challenge
+   */
+  struct ANASTASIS_CRYPTO_NonceP nonce;
+
+  /**
+   * Key used to encrypt the truth passed to the server
+   */
+  struct ANASTASIS_CRYPTO_TruthKeyP truth_key;
+
+  /**
+   * Salt used to encrypt the truth
+   */
+  struct ANASTASIS_CRYPTO_PowSalt truth_salt;
+
+  /**
+   * plaintext challenge which is sent to the client
+   */
+  void *challenge;
+
+  /**
+   * size of the challenge
+   */
+  size_t challenge_size;
+
+  /**
+   * method of the challenge
+   */
+  const char *escrow_method;
+
+  /**
+   * keyshare lookup operation
+   */
+  struct ANASTASIS_KeyShareLookupOperation *kslo;
+
+  /**
+   * Curl context
+   */
+  struct GNUNET_CURL_Context *ctx;
+
+  /**
+   * Encrypted key share
+   */
+  struct ANASTASIS_CRYPTO_KeyShareP *key_share;
+
+  /**
+   * Status of the challenge 0 pending, 1 solved
+   */
+  unsigned int solved;
+
+  /**
+   * Expected http status
+   */
+  unsigned int http_status;
+
+  /**
+   * Challenge instructions
+   */
+  const char *instructions;
+
+  /**
+   * Cost for authentication
+   */
+  struct TALER_Amount cost;
+
+  /**
+   * Passes back the payment information for the current challenge
+   */
+  ANASTASIS_ChallengePaymentCallback cpc;
+
+  /**
+   * Closure for the payment callback
+   */
+  void *cpc_cls;
+
+  /**
+   * The /truth GET operation handle.
+   */
+  struct ANASTASIS_ChallengeRunOperation *cro;
+
+  /**
+   * Sends back the status and the instructions of the challenge start
+   */
+  ANASTASIS_ChallengeStartCallback csc;
+
+  /**
+   * Closure for the Challenge Start
+   */
+  void *csc_cls;
+
+  /**
+   * Payment identifier.
+   */
+  struct ANASTASIS_PaymentSecretP payment_secret;
+
+  /**
+   * Payment order ID we got back, if any. Otherwise NULL.
+   */
+  char *payment_order_id;
+
+  /**
+   * Payment order ID we are to provide in the request, may be NULL.
+   */
+  const char *payment_order_req;
+
+  bool payment_requested;
+};
+
+
+struct ANASTASIS_ChallengeAnswerOperation
+{
+  struct ANASTASIS_Challenge *c;
+};
+
+
+/**
+ * Function called with the results of a #ANASTASIS_keyshare_lookup().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param ud details about the lookup operation
+ */
+static void
+keyshare_lookup_cb (void *cls,
+                    unsigned int http_status,
+                    const struct ANASTASIS_KeyShareDownloadDetails *dd)
+{
+  struct ANASTASIS_Challenge *c = cls;
+  c->kslo = NULL;
+  if (http_status != c->http_status)
+  {
+    c->af (c->af_cls,
+           http_status,
+           TALER_EC_INVALID); // FIXME: Error Code
+    return;
+  }
+  struct ANASTASIS_CRYPTO_UserIdentifierP id;
+  ANASTASIS_CRYPTO_user_identifier_derive (c->recovery->id_data,
+                                           &c->truth_salt,
+                                           &id);
+  ANASTASIS_CRYPTO_keyshare_decrypt (dd->encrypted_key_share,
+                                     &id,
+                                     &c->key_share);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "At %s:%d decrypted keyshare is %s-%llu b\n", __FILE__, __LINE__,
+              TALER_B2S (&c->key_share),
+              (unsigned long long) sizeof (c->key_share));
+
+  c->recovery->solved_challenges[c->recovery->solved_challenge_pos] = *c;
+  c->recovery->solved_challenge_pos++;
+  c->af (c->af_cls,
+         http_status,
+         TALER_EC_NONE);
+
+  /**
+   * 0 equals the challenge was not solved 1 it was solved
+   */
+  bool missing = true;
+  /**
+   * Index of the policy which was completed
+   */
+  unsigned int success = UINT_MAX;
+
+  for (unsigned int i = 0; i < c->recovery->ri->dps_len; i++)
+  {
+    for (unsigned int j = 0; j < c->recovery->ri->dps[i].nonces_length; j++)
+    {
+      missing = true;
+      for (unsigned int k = 0; k < c->recovery->solved_challenge_pos; k++)
+      {
+        if (0 == memcmp (&c->recovery->ri->dps[i].nonces[j],
+                         &c->recovery->solved_challenges[k].nonce,
+                         sizeof(struct ANASTASIS_CRYPTO_NonceP)))
+        {
+          missing = false;
+          break;
+        }
+      }
+      if (missing == true)
+      {
+        break;
+      }
+    }
+    if (missing == false)
+    {
+      success = i;
+      break;
+    }
+  }
+
+  if (success != UINT_MAX)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d policy was solved \n", __FILE__, __LINE__);
+    void *core_secret;
+    size_t core_secret_size;
+    struct ANASTASIS_CRYPTO_KeyShareP
+      key_shares[c->recovery->ri->dps[success].nonces_length];
+    struct ANASTASIS_CRYPTO_PolicyKeyP policy_key;
+    for (unsigned int l = 0; l < c->recovery->ri->dps[success].nonces_length;
+         l++)
+    {
+      for (unsigned int m = 0; m < c->recovery->solved_challenge_pos; m++)
+      {
+        if (0 == memcmp (&c->recovery->ri->dps[success].nonces[l],
+                         &c->recovery->solved_challenges[m].nonce,
+                         sizeof(struct ANASTASIS_CRYPTO_NonceP)))
+        {
+          key_shares[l] = *c->recovery->solved_challenges[m].key_share;
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "At %s:%d keyshare added %s-%llu b at position %x\n",
+                      __FILE__, __LINE__,
+                      TALER_B2S (&key_shares[l]),
+                      (unsigned long long) sizeof (c->key_share),
+                      l);
+        }
+      }
+    }
+    ANASTASIS_CRYPTO_policy_key_derive (key_shares,
+                                        c->recovery->ri->dps[success].
+                                        nonces_length,
+                                        &c->recovery->ri->dps[success].salt,
+                                        &policy_key);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d the policy key is %s-%llu b\n", __FILE__, __LINE__,
+                TALER_B2S (&policy_key),
+                (unsigned long long) sizeof (policy_key));
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
+                __LINE__,
+                TALER_b2s (c->recovery->enc_core_secret,
+                           c->recovery->enc_core_secret_size),
+                (unsigned long long) c->recovery->enc_core_secret_size);
+
+    ANASTASIS_CRYPTO_core_secret_recover (&c->recovery->ri->dps[success].emk,
+                                          policy_key,
+                                          c->recovery->enc_core_secret,
+                                          c->recovery->enc_core_secret_size,
+                                          &core_secret,
+                                          &core_secret_size);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d decrypted core secret is %s-%llu b\n", __FILE__,
+                __LINE__,
+                TALER_b2s (core_secret,
+                           core_secret_size),
+                (unsigned long long) core_secret_size);
+    c->recovery->csc (c->recovery->csc_cls,
+                      core_secret,
+                      core_secret_size);
+  }
+}
+
+
+/**
+ * Cancel a challenge answer operation.
+ *
+ * @param pso the challenge answer operation to cancel
+ */
+void
+ANASTASIS_challenge_answer_cancel (struct
+                                   ANASTASIS_ChallengeAnswerOperation *cao)
+{
+  if (NULL != cao->c)
+  {
+    GNUNET_free (cao->c);
+  }
+  GNUNET_free (cao);
+}
+
+
+struct ANASTASIS_ChallengeAnswerOperation *
+ANASTASIS_challenge_answer (struct GNUNET_CURL_Context *ctx,
+                            struct ANASTASIS_Challenge *c,
+                            const char *answer_str,
+                            ANASTASIS_AnswerFeedback af,
+                            void *af_cls)
+{
+  struct ANASTASIS_ChallengeAnswerOperation *cao;
+
+  cao = GNUNET_new (struct ANASTASIS_ChallengeAnswerOperation);
+  cao->c = c;
+  c->af = af;
+  c->ctx = ctx;
+  c->af_cls = af_cls;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "At %s:%d challenge answer is %s\n", __FILE__, __LINE__,
+              answer_str);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "At %s:%d challenge %s-%llu is solved with url %s \n", __FILE__,
+              __LINE__,
+              TALER_B2S (&c->truth_public_key),
+              (unsigned long long) sizeof (c->truth_public_key),
+              c->url);
+
+  c->http_status = MHD_HTTP_OK;
+  if (0 == strcmp (c->escrow_method,
+                   "question"))
+  {
+    struct GNUNET_HashCode hashed_answer;
+    char *str;
+
+    GNUNET_CRYPTO_hash (answer_str,
+                        strlen (answer_str),
+                        &hashed_answer);
+    str = GNUNET_STRINGS_data_to_string_alloc (&hashed_answer,
+                                               sizeof (hashed_answer));
+    c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
+                                         c->url,
+                                         &c->truth_public_key,
+                                         &c->truth_key,
+                                         c->payment_requested,
+                                         &c->payment_secret,
+                                         str,
+                                         &keyshare_lookup_cb,
+                                         c);
+    GNUNET_free (str);
+    if (NULL == c->kslo)
+    {
+      GNUNET_break (0);
+      return NULL;
+    }
+  }
+  else
+  {
+    c->kslo = ANASTASIS_keyshare_lookup (c->ctx,
+                                         c->url,
+                                         &c->truth_public_key,
+                                         &c->truth_key,
+                                         c->payment_requested,
+                                         &c->payment_secret,
+                                         answer_str,
+                                         &keyshare_lookup_cb,
+                                         c);
+    if (NULL == c->kslo)
+    {
+      GNUNET_break (0);
+      return NULL;
+    }
+  }
+  return cao;
+}
+
+
+struct ANASTASIS_ChallengeInformation *
+ANASTASIS_get_challenge (struct ANASTASIS_Challenge *challenge)
+{
+  struct ANASTASIS_ChallengeInformation *ci;
+
+  ci = GNUNET_new (struct ANASTASIS_ChallengeInformation);
+  ci->truth_public_key = &challenge->truth_public_key;
+  ci->method = challenge->escrow_method;
+  ci->url = challenge->url;
+  ci->nonce = &challenge->nonce;
+  ci->instructions = challenge->instructions;
+  ci->solved = challenge->solved;
+  ci->challenge = challenge;
+
+  return ci;
+}
+
+
+struct ANASTASIS_Challenge *
+ANASTASIS_json_to_challenge (json_t *challenge)
+{
+  GNUNET_assert (json_is_object (challenge));
+  const char *challenge_str;
+  struct ANASTASIS_Challenge *c = NULL;
+
+  challenge_str =
+    json_string_value (
+      json_object_get (challenge,
+                       "challenge"));
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_STRINGS_string_to_data (
+                   challenge_str,
+                   strlen (challenge_str),
+                   c,
+                   sizeof (struct ANASTASIS_Challenge)));
+  return c;
+}
+
+
+json_t *
+ANASTASIS_challenge_information_to_json (const struct
+                                         ANASTASIS_ChallengeInformation *ci)
+{
+  return json_pack ("{s:o,s:s,s:s,s:o,s:s:s:I,s:o}",
+                    "truth_public_key",
+                    GNUNET_JSON_from_data_auto (ci->truth_public_key),
+                    "method",
+                    ci->method,
+                    "url",
+                    ci->url,
+                    "nonce",
+                    GNUNET_JSON_from_data_auto (ci->nonce),
+                    "instructions",
+                    ci->instructions,
+                    "solved",
+                    (json_int_t) ci->solved,
+                    "challenge",
+                    GNUNET_JSON_from_data_auto (ci->challenge));
+}
+
+
+/**
+ * Function called with the results of a #ANASTASIS_challenge_run().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param response_string payment request or instructions
+ */
+static void
+challenge_run_cb (void *cls,
+                  unsigned int http_status,
+                  char *response_string)
+{
+  struct ANASTASIS_Challenge *c = cls;
+  c->cro = NULL;
+
+  if (http_status == MHD_HTTP_PAYMENT_REQUIRED)
+  {
+    const char *m;
+
+    if (0 != strncmp (response_string,
+                      "taler://pay/http",
+                      strlen ("taler://pay/http")))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Did not find `%s' in `%s'\n",
+                  "/-/-/",
+                  response_string);
+      /*FIXME ERROR*/
+      return;
+    }
+    m = strstr (response_string, "/-/-/");
+    if (NULL == m)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Did not find `%s' in `%s'\n",
+                  "/-/-/",
+                  response_string);
+      /*FIXME ERROR*/
+
+      /* NOTE: The above is a simplifying assumption for the
+         test-logic, hitting this code merely means that
+         the assumptions for the test (i.e. no instance) are
+         not satisfied, it is not inherently the case that
+         the above token must appear in the payment request!
+
+         So if you hit this, you might just want to modify
+         the code here to handle this better! */
+      return;
+    }
+    c->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                "Order ID from Anastasis service is `%s'\n",
+                c->payment_order_id);
+    c->cpc (c->cpc_cls,
+            response_string,
+            c->url,
+            http_status);
+    return;
+  }
+  c->csc (c->csc_cls,
+          response_string,
+          http_status);
+  return;
+}
+
+
+void
+ANASTASIS_challenge_start (struct GNUNET_CURL_Context *ctx,
+                           struct ANASTASIS_Challenge *c,
+                           ANASTASIS_ChallengePaymentCallback cpc,
+                           void *cpc_cls,
+                           ANASTASIS_ChallengeStartCallback csc,
+                           void *csc_cls)
+{
+  c->ctx = ctx;
+  c->csc = csc;
+  c->csc_cls = csc_cls;
+  c->cpc = cpc;
+  c->cpc_cls = cpc_cls;
+  c->payment_requested = false;
+
+  if (c->payment_order_id != NULL)
+  {
+    GNUNET_STRINGS_string_to_data (c->payment_order_id,
+                                   strlen (c->payment_order_id),
+                                   &c->payment_secret,
+                                   sizeof (struct
+                                           ANASTASIS_PaymentSecretP));
+    c->payment_requested = true;
+  }
+
+  c->cro = ANASTASIS_challenge_run (c->ctx,
+                                    c->url,
+                                    &c->truth_public_key,
+                                    &c->truth_key,
+                                    c->payment_requested
+                                    ? &c->payment_secret
+                                    : NULL,
+                                    c->payment_requested,
+                                    &challenge_run_cb,
+                                    c);
+  if (NULL == c->cro)
+  {
+    GNUNET_break (0);
+    return;
+  }
+}
+
+
+/**
+ * Function called with the results of a ANASTASIS_policy_lookup
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param ud details about the lookup operation
+ */
+static void
+policy_lookup_cb (void *cls,
+                  unsigned int http_status,
+                  const struct ANASTASIS_DownloadDetails *dd)
+{
+  struct ANASTASIS_Recovery *r = cls;
+  void *plaintext;
+  size_t size_plaintext;
+  json_t *recovery_document;
+  json_error_t json_error;
+  json_t *dec_policies;
+  json_t *esc_methods;
+
+  r->response_code = http_status;
+  r->ri = GNUNET_new (struct ANASTASIS_RecoveryInformation);
+  r->plo = NULL;
+  if (http_status != r->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u in %s:%u\n",
+                http_status,
+                __FILE__,
+                __LINE__);
+
+    r->pc (r->pc_cls,
+           r->ri,
+           TALER_EC_INVALID); // FIXME: Error Code
+    // r->pc = NULL;
+    ANASTASIS_recovery_abort (r);
+    return;
+  }
+  if (NULL == dd->policy)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No recovery data available");
+    r->pc (r->pc_cls,
+           r->ri,
+           TALER_EC_INVALID); // FIXME: Error Code
+    // r->pc = NULL;
+    ANASTASIS_recovery_abort (r);
+    return;
+  }
+  ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id,
+                                              dd->policy,
+                                              dd->policy_size,
+                                              &plaintext,
+                                              &size_plaintext);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "At %s:%d rec doc after enc is %s \n",
+              __FILE__, __LINE__,
+              TALER_b2s (plaintext, size_plaintext));
+  // FIXME COMPRESSION
+
+  recovery_document = json_loadb ((char *) plaintext,
+                                  size_plaintext,
+                                  JSON_DECODE_ANY,
+                                  &json_error);
+  GNUNET_free (plaintext);
+  if (NULL == recovery_document)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to read JSON input: %s at %d:%s (offset: %d)\n",
+                json_error.text,
+                json_error.line,
+                json_error.source,
+                json_error.position);
+    GNUNET_break_op (0);
+    r->pc (r->pc_cls,
+           r->ri,
+           TALER_EC_INVALID); // FIXME: Error Code
+    ANASTASIS_recovery_abort (r);
+    return;
+  }
+
+  struct GNUNET_JSON_Specification spec[] = {
+    GNUNET_JSON_spec_json ("policies",
+                           &dec_policies),
+    GNUNET_JSON_spec_json ("escrow_methods",
+                           &esc_methods),
+    GNUNET_JSON_spec_varsize ("core_secret",
+                              &r->enc_core_secret,
+                              &r->enc_core_secret_size),
+    GNUNET_JSON_spec_end ()
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_JSON_parse (recovery_document,
+                         spec,
+                         NULL, NULL))
+  {
+    GNUNET_break_op (0);
+    json_decref (recovery_document);
+    recovery_document = NULL;
+    GNUNET_JSON_parse_free (spec);
+    r->pc (r->pc_cls,
+           r->ri,
+           TALER_EC_INVALID); // FIXME: Error Code
+    ANASTASIS_recovery_abort (r);
+    return;
+  }
+  json_decref (recovery_document);
+  recovery_document = NULL;
+  r->ri->cs_len = json_array_size (esc_methods);
+  r->ri->dps_len = json_array_size (dec_policies);
+  r->ri->dps = GNUNET_new_array (r->ri->dps_len,
+                                 struct ANASTASIS_DecryptionPolicy);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "At %s:%d encrypted core secret is %s-%llu b\n", __FILE__,
+              __LINE__,
+              TALER_b2s (r->enc_core_secret,
+                         r->enc_core_secret_size),
+              (unsigned long long) r->enc_core_secret_size);
+  r->solved_challenges = GNUNET_new_array (r->ri->cs_len,
+                                           struct ANASTASIS_Challenge);
+
+  struct ANASTASIS_Challenge **cs = GNUNET_new_array (r->ri->cs_len,
+                                                      struct 
ANASTASIS_Challenge
+                                                      *);
+  for (unsigned int i = 0; i < r->ri->cs_len; i++)
+  {
+    cs[i] = GNUNET_new (struct ANASTASIS_Challenge);
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("nonce",
+                                   &cs[i]->nonce),
+      GNUNET_JSON_spec_string ("url",
+                               &cs[i]->url),
+      GNUNET_JSON_spec_string ("instructions",
+                               &cs[i]->instructions),
+      GNUNET_JSON_spec_fixed_auto ("truth_key",
+                                   &cs[i]->truth_key),
+      GNUNET_JSON_spec_fixed_auto ("salt",
+                                   &cs[i]->truth_salt),
+      GNUNET_JSON_spec_string ("escrow_method",
+                               &cs[i]->escrow_method),
+      GNUNET_JSON_spec_end ()
+    };
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (json_array_get (esc_methods, i),
+                           spec,
+                           NULL, NULL))
+    {
+      GNUNET_break_op (0);
+      json_decref (esc_methods);
+      GNUNET_JSON_parse_free (spec);
+      r->pc (r->pc_cls,
+             r->ri,
+             TALER_EC_INVALID); // FIXME: Error Code
+      ANASTASIS_recovery_abort (r);
+      return;
+    }
+    ANASTASIS_CRYPTO_truth_public_key_derive (&cs[i]->nonce,
+                                              &cs[i]->truth_public_key);
+    cs[i]->recovery = r;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d challenge public key is %s-%llu b\n", __FILE__,
+                __LINE__,
+                TALER_B2S (&cs[i]->truth_public_key),
+                (unsigned long long) sizeof (cs[i]->truth_public_key));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d url is %s\n", __FILE__, __LINE__,
+                cs[i]->url);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d truth key is %s-%llu b\n", __FILE__, __LINE__,
+                TALER_B2S (&cs[i]->truth_key),
+                (unsigned long long) sizeof (cs[i]->truth_key));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d truth_salt is %s-%llu b\n", __FILE__, __LINE__,
+                TALER_B2S (&cs[i]->truth_salt),
+                (unsigned long long) sizeof (cs[i]->truth_salt));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d escrow method is %s\n", __FILE__, __LINE__,
+                cs[i]->escrow_method);
+  }
+
+  for (unsigned int j = 0; j < r->ri->dps_len; j++)
+  {
+    size_t n_index;
+    json_t *nonces;
+    json_t *nonce;
+
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("master_key",
+                                   &r->ri->dps[j].emk),
+      GNUNET_JSON_spec_fixed_auto ("salt",
+                                   &r->ri->dps[j].salt),
+      GNUNET_JSON_spec_uint32 ("nonces_length",
+                               &r->ri->dps[j].nonces_length),
+      GNUNET_JSON_spec_end ()
+    };
+    nonces = json_object_get (json_array_get (dec_policies, j),
+                              "nonces");
+    GNUNET_assert (json_is_array (nonces));
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (json_array_get (dec_policies, j),
+                           spec,
+                           NULL, NULL))
+    {
+      GNUNET_break_op (0);
+      GNUNET_JSON_parse_free (spec);
+      json_decref (dec_policies);
+      r->pc (r->pc_cls,
+             r->ri,
+             TALER_EC_INVALID); // FIXME: Error Code
+      ANASTASIS_recovery_abort (r);
+      return;
+    }
+
+    r->ri->dps[j].nonces = GNUNET_new_array (r->ri->dps[j].nonces_length,
+                                             struct ANASTASIS_CRYPTO_NonceP);
+
+    json_array_foreach (nonces, n_index, nonce)
+    {
+      const char *nonce_str = json_string_value (nonce);
+      GNUNET_STRINGS_string_to_data (nonce_str,
+                                     strlen (nonce_str),
+                                     &r->ri->dps[j].nonces[n_index],
+                                     sizeof (struct ANASTASIS_CRYPTO_NonceP));
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "At %s:%d escrow nonce is %s-%llu b\n",
+                  __FILE__, __LINE__,
+                  TALER_B2S (&r->ri->dps[j].nonces[n_index]),
+                  (unsigned long long) sizeof (r->ri->dps[j].nonces[n_index]));
+    }
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d encrypted master key is %s-%llu b\n",
+                __FILE__,  __LINE__,
+                TALER_B2S (&r->ri->dps[j].emk),
+                (unsigned long long) sizeof (r->ri->dps[j].emk));
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "At %s:%d policy salt is %s-%llu b\n",
+                __FILE__, __LINE__,
+                TALER_B2S (&r->ri->dps[j].salt),
+                (unsigned long long) sizeof (r->ri->dps[j].salt));
+  }
+  r->solved_challenge_pos = 0;
+  r->ri->cs = cs;
+  // SETUP POLICY CALLBACK
+  if (NULL != r->pc)
+  {
+    r->pc (r->pc_cls,
+           r->ri,
+           TALER_EC_NONE); // FIXME: Error Code
+    // r->pc = NULL;
+  }
+  json_decref (esc_methods);
+  json_decref (dec_policies);
+}
+
+
+/**
+* Starts the recovery process by opening callbacks for the coresecret and a 
policy callback. A list of
+* providers is checked for policies and passed back to the client.
+*
+* @param ctx the CURL context used to connect to the backend
+* @param id_data contains the users identity, (user account on providers)
+* @param version defines the version which will be downloaded NULL for latest 
version
+* @param anastasis_provider_url NULL terminated list of possible provider urls
+* @param salt the server salt
+* @param pc opens the policy call back which holds the downloaded version and 
the policies
+* @param pc_cls closure for callback
+* @param csc core secret callback is opened, with this the core secert is 
passed to the client after the authentication
+* @param csc_cls handle for the callback
+*/
+struct ANASTASIS_Recovery *
+ANASTASIS_recovery_begin (struct GNUNET_CURL_Context *ctx,
+                          const json_t *id_data,
+                          unsigned int version,
+                          const char *anastasis_provider_url,
+                          const struct ANASTASIS_CRYPTO_PowSalt *salt,
+                          ANASTASIS_PolicyCallback pc,
+                          void *pc_cls,
+                          ANASTASIS_CoreSecretCallback csc,
+                          void *csc_cls)
+{
+  struct ANASTASIS_Recovery *r;
+
+  r = GNUNET_new (struct ANASTASIS_Recovery);
+  r->csc = csc;
+  r->csc_cls = csc_cls;
+  r->pc = pc;
+  r->pc_cls = pc_cls;
+  r->ctx = ctx;
+  r->id_data = id_data;
+  r->http_status = MHD_HTTP_OK;
+  ANASTASIS_CRYPTO_user_identifier_derive (id_data,
+                                           salt,
+                                           &r->id);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "At %s:%d user_identfier is %s-%llu b\n",
+              __FILE__, __LINE__,
+              TALER_B2S (&r->id),
+              (unsigned long long) sizeof (r->id));
+  ANASTASIS_CRYPTO_account_public_key_derive (&r->id,
+                                              &r->pub_key);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "At %s:%d public key is %s-%llu b\n",
+              __FILE__, __LINE__,
+              TALER_B2S (&r->pub_key),
+              (unsigned long long) sizeof (r->pub_key));
+
+  if (version != 0)
+  {
+    r->plo = ANASTASIS_policy_lookup_version (r->ctx,
+                                              anastasis_provider_url,
+                                              &r->pub_key,
+                                              &policy_lookup_cb,
+                                              r,
+                                              &version);
+    if (NULL == r->plo)
+    {
+      GNUNET_break (0);
+      return NULL;
+    }
+  }
+  else
+  {
+    r->plo = ANASTASIS_policy_lookup (r->ctx,
+                                      anastasis_provider_url,
+                                      &r->pub_key,
+                                      &policy_lookup_cb,
+                                      r);
+    if (NULL == r->plo)
+    {
+      GNUNET_break (0);
+      return NULL;
+    }
+  }
+
+  return r;
+}
+
+
+void
+ANASTASIS_recovery_free (struct ANASTASIS_Recovery *r)
+{
+  GNUNET_free (r->solved_challenges);
+  GNUNET_free (r->encrypted_recovery_document);
+  GNUNET_free (r->ri->dps);
+  GNUNET_free (r->ri->cs);
+  GNUNET_free (r->ri);
+  GNUNET_free (r);
+}
+
+
+/**
+* Cancels the recovery process
+* @param r handle to the recovery struct
+*/
+void
+ANASTASIS_recovery_abort (struct ANASTASIS_Recovery *r)
+{
+  if (NULL != r->plo)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "policy lookup aborted");
+    ANASTASIS_policy_lookup_cancel (r->plo);
+    r->plo = NULL;
+  }
+  ANASTASIS_recovery_free (r);
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]