anastasis_recovery.c (44629B)
1 /* 2 This file is part of Anastasis 3 Copyright (C) 2020, 2021 Anastasis SARL 4 5 Anastasis is free software; you can redistribute it and/or modify it under the 6 terms of the GNU General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License along with 14 Anastasis; see the file COPYING.GPL. If not, see <http://www.gnu.org/licenses/> 15 */ 16 /** 17 * @brief anastasis client api 18 * @author Christian Grothoff 19 * @author Dominik Meister 20 * @author Dennis Neufeld 21 */ 22 #include "platform.h" 23 #include "anastasis.h" 24 #include <taler/taler_json_lib.h> 25 #include <gnunet/gnunet_util_lib.h> 26 #include <taler/taler_merchant_service.h> 27 #include <zlib.h> 28 #include <microhttpd.h> 29 30 31 /** 32 * Challenge struct contains the uuid and public key's needed for the 33 * recovery process and a reference to ANASTASIS_Recovery. 34 */ 35 struct ANASTASIS_Challenge 36 { 37 38 /** 39 * Information exported to clients about this challenge. 40 */ 41 struct ANASTASIS_ChallengeDetails ci; 42 43 /** 44 * Key used to encrypt the truth passed to the server 45 */ 46 struct ANASTASIS_CRYPTO_TruthKeyP truth_key; 47 48 /** 49 * Salt; used to derive hash from security question answers. 50 */ 51 struct ANASTASIS_CRYPTO_QuestionSaltP question_salt; 52 53 /** 54 * Provider salt; used to derive our key material from our identity 55 * key. 56 */ 57 struct ANASTASIS_CRYPTO_ProviderSaltP provider_salt; 58 59 /** 60 * Decrypted key share for this challenge. Set once the 61 * challenge was @e ri.solved. 62 */ 63 struct ANASTASIS_CRYPTO_KeyShareP key_share; 64 65 /** 66 * Callback which gives back the instructions and a status code of 67 * the request to the user when answering a challenge. 68 */ 69 ANASTASIS_AnswerFeedback af; 70 71 /** 72 * Closure for @e af. 73 */ 74 void *af_cls; 75 76 /** 77 * Callback which gives back the instructions and a status code of 78 * the request to the user when initiating a challenge. 79 */ 80 ANASTASIS_ChallengeStartFeedback csf; 81 82 /** 83 * Closure for @e csf. 84 */ 85 void *csf_cls; 86 87 /** 88 * Defines the base URL of the Anastasis provider used for the challenge. 89 */ 90 char *url; 91 92 /** 93 * What is the type of this challenge (E-Mail, Security Question, SMS...) 94 */ 95 char *type; 96 97 /** 98 * Instructions for solving the challenge (generic, set client-side 99 * when challenge was established). 100 */ 101 char *instructions; 102 103 /** 104 * Answer to the security question, if @a type is "question". Otherwise NULL. 105 */ 106 char *answer; 107 108 /** 109 * Reference to the recovery process which is ongoing 110 */ 111 struct ANASTASIS_Recovery *recovery; 112 113 /** 114 * Handle for the /truth/$TID/challenge request. 115 */ 116 struct ANASTASIS_TruthChallengeOperation *tco; 117 118 /** 119 * Handle for the /truth/$TID/solve request. 120 */ 121 struct ANASTASIS_TruthSolveOperation *tso; 122 123 }; 124 125 126 /** 127 * Defines a decryption policy with multiple escrow methods 128 */ 129 struct DecryptionPolicy 130 { 131 132 /** 133 * Publicly visible details about a decryption policy. 134 */ 135 struct ANASTASIS_DecryptionPolicy pub_details; 136 137 /** 138 * Encrypted master key (encrypted with the policy key). 139 */ 140 void *emk; 141 142 /** 143 * Size of the encrypted master key. 144 */ 145 size_t emk_size; 146 147 /** 148 * Salt used to decrypt master key. 149 */ 150 struct ANASTASIS_CRYPTO_MasterSaltP master_salt; 151 152 }; 153 154 155 /** 156 * stores provider URLs, identity key material, decrypted recovery document (internally!) 157 */ 158 struct ANASTASIS_Recovery 159 { 160 161 /** 162 * Identity key material used for the derivation of keys 163 */ 164 struct ANASTASIS_CRYPTO_UserIdentifierP id; 165 166 /** 167 * Recovery information which is given to the user 168 */ 169 struct ANASTASIS_RecoveryInformation ri; 170 171 /** 172 * Internal of @e ri.dps_len policies that would allow recovery of the core secret. 173 */ 174 struct DecryptionPolicy *dps; 175 176 /** 177 * Array of @e ri.cs_len challenges to be solved (for any of the policies). 178 */ 179 struct ANASTASIS_Challenge *cs; 180 181 /** 182 * Identity data to user id from. 183 */ 184 json_t *id_data; 185 186 /** 187 * Callback to send back a recovery document with the policies and the version 188 */ 189 ANASTASIS_PolicyCallback pc; 190 191 /** 192 * closure for the Policy callback 193 */ 194 void *pc_cls; 195 196 /** 197 * Callback to send back the core secret which was saved by 198 * anastasis, after all challenges are completed 199 */ 200 ANASTASIS_CoreSecretCallback csc; 201 202 /** 203 * Closure for the core secret callback 204 */ 205 void *csc_cls; 206 207 /** 208 * Curl context 209 */ 210 struct GNUNET_CURL_Context *ctx; 211 212 /** 213 * Reference to the policy lookup operation which is executed 214 */ 215 struct ANASTASIS_PolicyLookupOperation *plo; 216 217 /** 218 * Array of challenges that have been solved. 219 * Valid entries up to @e solved_challenge_pos. 220 * Length matches the total number of challenges in @e ri. 221 */ 222 struct ANASTASIS_Challenge **solved_challenges; 223 224 /** 225 * Our provider URL. 226 */ 227 char *provider_url; 228 229 /** 230 * Name of the secret, can be NULL. 231 */ 232 char *secret_name; 233 234 /** 235 * Task to run @e pc asynchronously. 236 */ 237 struct GNUNET_SCHEDULER_Task *do_async; 238 239 /** 240 * Retrieved encrypted core secret from policy 241 */ 242 void *enc_core_secret; 243 244 /** 245 * Size of the @e enc_core_secret 246 */ 247 size_t enc_core_secret_size; 248 249 /** 250 * Current offset in the @e solved_challenges array. 251 */ 252 unsigned int solved_challenge_pos; 253 254 }; 255 256 257 /** 258 * Function called with the results of a #ANASTASIS_challenge_start(). 259 * 260 * @param cls closure 261 * @param dd details about the lookup operation 262 */ 263 static void 264 truth_challenge_cb (void *cls, 265 const struct ANASTASIS_TruthChallengeDetails *tcd) 266 { 267 struct ANASTASIS_Challenge *c = cls; 268 struct ANASTASIS_ChallengeStartResponse csr = { 269 .challenge = c, 270 .ec = tcd->ec, 271 .http_status = tcd->http_status 272 }; 273 274 c->tco = NULL; 275 switch (tcd->http_status) 276 { 277 case MHD_HTTP_OK: 278 switch (tcd->details.success.cs) 279 { 280 case ANASTASIS_CS_FILE_WRITTEN: 281 csr.cs = ANASTASIS_CHALLENGE_START_STATUS_FILENAME_PROVIDED; 282 csr.details.tan_filename 283 = tcd->details.success.details.challenge_filename; 284 break; 285 case ANASTASIS_CS_TAN_SENT: 286 csr.cs = ANASTASIS_CHALLENGE_START_STATUS_TAN_SENT_HINT_PROVIDED; 287 csr.details.tan_address_hint 288 = tcd->details.success.details.tan_address_hint; 289 break; 290 case ANASTASIS_CS_TAN_ALREADY_SENT: 291 csr.cs = ANASTASIS_CHALLENGE_START_STATUS_TAN_ALREADY_SENT; 292 break; 293 case ANASTASIS_CS_WIRE_FUNDS: 294 csr.cs = ANASTASIS_CHALLENGE_START_STATUS_BANK_TRANSFER_REQUIRED; 295 csr.details.bank_transfer_required 296 = tcd->details.success.details.wire_funds; 297 break; 298 } 299 break; 300 case MHD_HTTP_PAYMENT_REQUIRED: 301 csr.cs = ANASTASIS_CHALLENGE_START_STATUS_PAYMENT_REQUIRED; 302 csr.details.payment_required.taler_pay_uri 303 = tcd->details.payment_required.payment_request; 304 csr.details.payment_required.payment_secret 305 = tcd->details.payment_required.ps; 306 break; 307 case MHD_HTTP_NOT_FOUND: 308 csr.cs = ANASTASIS_CHALLENGE_START_STATUS_TRUTH_UNKNOWN; 309 break; 310 default: 311 csr.cs = ANASTASIS_CHALLENGE_START_STATUS_SERVER_FAILURE; 312 break; 313 } 314 c->csf (c->csf_cls, 315 &csr); 316 } 317 318 319 /** 320 * Function called with the results of a #ANASTASIS_truth_solve(). 321 * 322 * @param cls closure 323 * @param tsr details about the solution response 324 */ 325 static void 326 truth_solve_cb (void *cls, 327 const struct ANASTASIS_TruthSolveReply *tsr) 328 { 329 struct ANASTASIS_Challenge *c = cls; 330 struct ANASTASIS_Recovery *recovery = c->recovery; 331 struct ANASTASIS_CRYPTO_UserIdentifierP id; 332 struct DecryptionPolicy *rdps; 333 struct ANASTASIS_ChallengeAnswerResponse csr = { 334 .challenge = c, 335 .ec = tsr->ec, 336 .http_status = tsr->http_status 337 }; 338 339 340 c->tso = NULL; 341 switch (tsr->http_status) 342 { 343 case MHD_HTTP_OK: 344 break; 345 case MHD_HTTP_PAYMENT_REQUIRED: 346 csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_PAYMENT_REQUIRED; 347 csr.details.payment_required.taler_pay_uri 348 = tsr->details.payment_required.payment_request; 349 csr.details.payment_required.payment_secret 350 = tsr->details.payment_required.ps; 351 c->af (c->af_cls, 352 &csr); 353 return; 354 case MHD_HTTP_FORBIDDEN: 355 csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_INVALID_ANSWER; 356 c->af (c->af_cls, 357 &csr); 358 return; 359 case MHD_HTTP_NOT_FOUND: 360 csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_TRUTH_UNKNOWN; 361 c->af (c->af_cls, 362 &csr); 363 return; 364 case MHD_HTTP_TOO_MANY_REQUESTS: 365 csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_RATE_LIMIT_EXCEEDED; 366 csr.details.rate_limit_exceeded.request_limit 367 = tsr->details.too_many_requests.request_limit; 368 csr.details.rate_limit_exceeded.request_frequency 369 = tsr->details.too_many_requests.request_frequency; 370 c->af (c->af_cls, 371 &csr); 372 return; 373 default: 374 csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_SERVER_FAILURE; 375 c->af (c->af_cls, 376 &csr); 377 return; 378 } 379 380 ANASTASIS_CRYPTO_user_identifier_derive (recovery->id_data, 381 &c->provider_salt, 382 &id); 383 ANASTASIS_CRYPTO_keyshare_decrypt (&tsr->details.success.eks, 384 &id, 385 c->answer, 386 &c->key_share); 387 recovery->solved_challenges[recovery->solved_challenge_pos++] = c; 388 c->ci.solved = true; 389 csr.cs = ANASTASIS_CHALLENGE_ANSWER_STATUS_SOLVED; 390 c->af (c->af_cls, 391 &csr); 392 393 /* Check if there is a policy for which all challenges have 394 been satisfied, if so, store it in 'rdps'. */ 395 rdps = NULL; 396 for (unsigned int i = 0; i < recovery->ri.dps_len; i++) 397 { 398 struct DecryptionPolicy *dps = &recovery->dps[i]; 399 bool missing = false; 400 401 for (unsigned int j = 0; j < dps->pub_details.challenges_length; j++) 402 { 403 bool found = false; 404 405 for (unsigned int k = 0; k < recovery->solved_challenge_pos; k++) 406 { 407 if (dps->pub_details.challenges[j] == recovery->solved_challenges[k]) 408 { 409 found = true; 410 break; 411 } 412 } 413 if (! found) 414 { 415 missing = true; 416 break; 417 } 418 } 419 if (! missing) 420 { 421 rdps = dps; 422 break; 423 } 424 } 425 if (NULL == rdps) 426 return; 427 428 { 429 void *core_secret; 430 size_t core_secret_size; 431 struct ANASTASIS_CRYPTO_KeyShareP 432 key_shares[rdps->pub_details.challenges_length]; 433 struct ANASTASIS_CRYPTO_PolicyKeyP policy_key; 434 435 for (unsigned int l = 0; l < rdps->pub_details.challenges_length; l++) 436 for (unsigned int m = 0; m < recovery->solved_challenge_pos; m++) 437 if (rdps->pub_details.challenges[l] == recovery->solved_challenges[m]) 438 key_shares[l] = recovery->solved_challenges[m]->key_share; 439 ANASTASIS_CRYPTO_policy_key_derive (key_shares, 440 rdps->pub_details.challenges_length, 441 &rdps->master_salt, 442 &policy_key); 443 GNUNET_assert (NULL != rdps->emk); 444 GNUNET_assert (rdps->emk_size > 0); 445 ANASTASIS_CRYPTO_core_secret_recover (rdps->emk, 446 rdps->emk_size, 447 &policy_key, 448 recovery->enc_core_secret, 449 recovery->enc_core_secret_size, 450 &core_secret, 451 &core_secret_size); 452 recovery->csc (recovery->csc_cls, 453 ANASTASIS_RS_SUCCESS, 454 core_secret, 455 core_secret_size); 456 GNUNET_free (core_secret); 457 ANASTASIS_recovery_abort (recovery); 458 } 459 } 460 461 462 const struct ANASTASIS_ChallengeDetails * 463 ANASTASIS_challenge_get_details (struct ANASTASIS_Challenge *challenge) 464 { 465 return &challenge->ci; 466 } 467 468 469 enum GNUNET_GenericReturnValue 470 ANASTASIS_challenge_start (struct ANASTASIS_Challenge *c, 471 const struct ANASTASIS_PaymentSecretP *psp, 472 ANASTASIS_ChallengeStartFeedback csf, 473 void *csf_cls) 474 { 475 if (c->ci.solved) 476 { 477 GNUNET_break (0); 478 return GNUNET_NO; /* already solved */ 479 } 480 if (NULL != c->tco) 481 { 482 GNUNET_break (0); 483 return GNUNET_NO; /* already solving */ 484 } 485 c->csf = csf; 486 c->csf_cls = csf_cls; 487 c->tco = ANASTASIS_truth_challenge (c->recovery->ctx, 488 c->url, 489 &c->ci.uuid, 490 &c->truth_key, 491 psp, 492 &truth_challenge_cb, 493 c); 494 if (NULL == c->tco) 495 { 496 GNUNET_break (0); 497 return GNUNET_SYSERR; 498 } 499 return GNUNET_OK; 500 } 501 502 503 enum GNUNET_GenericReturnValue 504 ANASTASIS_challenge_answer3 (struct ANASTASIS_Challenge *c, 505 const struct ANASTASIS_PaymentSecretP *psp, 506 struct GNUNET_TIME_Relative timeout, 507 const struct GNUNET_HashCode *hashed_answer, 508 ANASTASIS_AnswerFeedback af, 509 void *af_cls) 510 { 511 if (c->ci.solved) 512 { 513 GNUNET_break (0); 514 return GNUNET_NO; /* already solved */ 515 } 516 if (NULL != c->tso) 517 { 518 GNUNET_break (0); 519 return GNUNET_NO; /* already solving */ 520 } 521 c->af = af; 522 c->af_cls = af_cls; 523 c->tso = ANASTASIS_truth_solve (c->recovery->ctx, 524 c->url, 525 &c->ci.uuid, 526 &c->truth_key, 527 psp, 528 timeout, 529 hashed_answer, 530 &truth_solve_cb, 531 c); 532 if (NULL == c->tso) 533 { 534 GNUNET_break (0); 535 return GNUNET_SYSERR; 536 } 537 return GNUNET_OK; 538 } 539 540 541 enum GNUNET_GenericReturnValue 542 ANASTASIS_challenge_answer ( 543 struct ANASTASIS_Challenge *c, 544 const struct ANASTASIS_PaymentSecretP *psp, 545 struct GNUNET_TIME_Relative timeout, 546 const char *answer_str, 547 ANASTASIS_AnswerFeedback af, 548 void *af_cls) 549 { 550 struct GNUNET_HashCode hashed_answer; 551 552 GNUNET_free (c->answer); 553 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 554 "Answer to challenge is `%s'\n", 555 answer_str); 556 c->answer = GNUNET_strdup (answer_str); 557 ANASTASIS_CRYPTO_secure_answer_hash (answer_str, 558 &c->ci.uuid, 559 &c->question_salt, 560 &hashed_answer); 561 return ANASTASIS_challenge_answer3 (c, 562 psp, 563 timeout, 564 &hashed_answer, 565 af, 566 af_cls); 567 } 568 569 570 enum GNUNET_GenericReturnValue 571 ANASTASIS_challenge_answer2 (struct ANASTASIS_Challenge *c, 572 const struct ANASTASIS_PaymentSecretP *psp, 573 struct GNUNET_TIME_Relative timeout, 574 uint64_t answer, 575 ANASTASIS_AnswerFeedback af, 576 void *af_cls) 577 { 578 struct GNUNET_HashCode answer_s; 579 580 GNUNET_log (GNUNET_ERROR_TYPE_INFO, 581 "Answer to challenge is %llu\n", 582 (unsigned long long) answer); 583 ANASTASIS_hash_answer (answer, 584 &answer_s); 585 return ANASTASIS_challenge_answer3 (c, 586 psp, 587 timeout, 588 &answer_s, 589 af, 590 af_cls); 591 } 592 593 594 void 595 ANASTASIS_challenge_abort (struct ANASTASIS_Challenge *c) 596 { 597 if (NULL != c->tso) 598 { 599 ANASTASIS_truth_solve_cancel (c->tso); 600 c->tso = NULL; 601 } 602 if (NULL != c->tco) 603 { 604 ANASTASIS_truth_challenge_cancel (c->tco); 605 c->tco = NULL; 606 } 607 c->af = NULL; 608 c->af_cls = NULL; 609 } 610 611 612 /** 613 * Function called with the results of a #ANASTASIS_policy_lookup() 614 * 615 * @param cls closure 616 * @param dd details about the lookup operation 617 */ 618 static void 619 policy_lookup_cb (void *cls, 620 const struct ANASTASIS_DownloadDetails *dd) 621 { 622 struct ANASTASIS_Recovery *r = cls; 623 void *plaintext; 624 size_t size_plaintext; 625 json_error_t json_error; 626 const json_t *dec_policies; 627 const json_t *esc_methods; 628 json_t *recovery_document; 629 630 r->plo = NULL; 631 switch (dd->http_status) 632 { 633 case MHD_HTTP_OK: 634 break; 635 case MHD_HTTP_NOT_FOUND: 636 r->csc (r->csc_cls, 637 ANASTASIS_RS_POLICY_UNKNOWN, 638 NULL, 639 0); 640 ANASTASIS_recovery_abort (r); 641 return; 642 case MHD_HTTP_NO_CONTENT: 643 /* Account known, policy expired */ 644 r->csc (r->csc_cls, 645 ANASTASIS_RS_POLICY_GONE, 646 NULL, 647 0); 648 ANASTASIS_recovery_abort (r); 649 return; 650 case MHD_HTTP_INTERNAL_SERVER_ERROR: 651 /* Bad server... */ 652 r->csc (r->csc_cls, 653 ANASTASIS_RS_POLICY_SERVER_ERROR, 654 NULL, 655 0); 656 ANASTASIS_recovery_abort (r); 657 return; 658 case MHD_HTTP_NOT_MODIFIED: 659 /* Should not be possible, we do not cache, fall-through! */ 660 default: 661 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 662 "Unexpected response code %u in %s:%u\n", 663 dd->http_status, 664 __FILE__, 665 __LINE__); 666 r->csc (r->csc_cls, 667 ANASTASIS_RS_POLICY_DOWNLOAD_FAILED, 668 NULL, 669 0); 670 ANASTASIS_recovery_abort (r); 671 return; 672 } 673 if (NULL == dd->details.ok.policy) 674 { 675 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 676 "No recovery data available"); 677 r->csc (r->csc_cls, 678 ANASTASIS_RS_POLICY_DOWNLOAD_NO_POLICY, 679 NULL, 680 0); 681 ANASTASIS_recovery_abort (r); 682 return; 683 } 684 ANASTASIS_CRYPTO_recovery_document_decrypt (&r->id, 685 dd->details.ok.policy, 686 dd->details.ok.policy_size, 687 &plaintext, 688 &size_plaintext); 689 if (size_plaintext < sizeof (uint32_t)) 690 { 691 GNUNET_break_op (0); 692 r->csc (r->csc_cls, 693 ANASTASIS_RS_POLICY_DOWNLOAD_INVALID_COMPRESSION, 694 NULL, 695 0); 696 ANASTASIS_recovery_abort (r); 697 GNUNET_free (plaintext); 698 return; 699 } 700 { 701 uint32_t be_size; 702 uLongf pt_size; 703 char *pt; 704 705 memcpy (&be_size, 706 plaintext, 707 sizeof (uint32_t)); 708 pt_size = ntohl (be_size); 709 pt = GNUNET_malloc_large (pt_size); 710 if (NULL == pt) 711 { 712 GNUNET_break_op (0); 713 r->csc (r->csc_cls, 714 ANASTASIS_RS_POLICY_DOWNLOAD_TOO_BIG, 715 NULL, 716 0); 717 ANASTASIS_recovery_abort (r); 718 GNUNET_free (plaintext); 719 return; 720 } 721 if (Z_OK != 722 uncompress ((Bytef *) pt, 723 &pt_size, 724 (const Bytef *) plaintext + sizeof (uint32_t), 725 size_plaintext - sizeof (uint32_t))) 726 { 727 GNUNET_break_op (0); 728 r->csc (r->csc_cls, 729 ANASTASIS_RS_POLICY_DOWNLOAD_INVALID_COMPRESSION, 730 NULL, 731 0); 732 GNUNET_free (plaintext); 733 GNUNET_free (pt); 734 ANASTASIS_recovery_abort (r); 735 return; 736 } 737 GNUNET_free (plaintext); 738 recovery_document = json_loadb ((char *) pt, 739 pt_size, 740 JSON_DECODE_ANY, 741 &json_error); 742 GNUNET_free (pt); 743 if (NULL == recovery_document) 744 { 745 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 746 "Failed to read JSON input: %s at %d:%s (offset: %d)\n", 747 json_error.text, 748 json_error.line, 749 json_error.source, 750 json_error.position); 751 GNUNET_break_op (0); 752 r->csc (r->csc_cls, 753 ANASTASIS_RS_POLICY_DOWNLOAD_NO_JSON, 754 NULL, 755 0); 756 ANASTASIS_recovery_abort (r); 757 return; 758 } 759 760 { 761 const char *secret_name = NULL; 762 struct GNUNET_JSON_Specification spec[] = { 763 GNUNET_JSON_spec_array_const ("policies", 764 &dec_policies), 765 GNUNET_JSON_spec_array_const ("escrow_methods", 766 &esc_methods), 767 GNUNET_JSON_spec_mark_optional ( 768 GNUNET_JSON_spec_string ("secret_name", 769 &secret_name), 770 NULL), 771 GNUNET_JSON_spec_varsize ("encrypted_core_secret", 772 &r->enc_core_secret, 773 &r->enc_core_secret_size), 774 GNUNET_JSON_spec_end () 775 }; 776 777 if (GNUNET_OK != 778 GNUNET_JSON_parse (recovery_document, 779 spec, 780 NULL, NULL)) 781 { 782 GNUNET_break_op (0); 783 json_dumpf (recovery_document, 784 stderr, 785 0); 786 r->csc (r->csc_cls, 787 ANASTASIS_RS_POLICY_MALFORMED_JSON, 788 NULL, 789 0); 790 goto cleanup; 791 } 792 if (NULL != secret_name) 793 { 794 GNUNET_break (NULL == r->secret_name); 795 r->secret_name = GNUNET_strdup (secret_name); 796 r->ri.secret_name = r->secret_name; 797 } 798 } 799 } 800 801 if ( (json_array_size (esc_methods) > UINT_MAX) || 802 (json_array_size (dec_policies) > UINT_MAX) ) 803 { 804 GNUNET_break_op (0); 805 r->csc (r->csc_cls, 806 ANASTASIS_RS_POLICY_DOWNLOAD_TOO_BIG, 807 NULL, 808 0); 809 goto cleanup; 810 } 811 812 r->ri.version = dd->details.ok.version; 813 r->ri.cs_len 814 = (unsigned int) json_array_size (esc_methods); 815 r->ri.dps_len 816 = (unsigned int) json_array_size (dec_policies); 817 r->ri.dps 818 = GNUNET_new_array (r->ri.dps_len, 819 struct ANASTASIS_DecryptionPolicy *); 820 r->dps 821 = GNUNET_new_array (r->ri.dps_len, 822 struct DecryptionPolicy); 823 r->solved_challenges 824 = GNUNET_new_array (r->ri.cs_len, 825 struct ANASTASIS_Challenge *); 826 r->ri.cs 827 = GNUNET_new_array (r->ri.cs_len, 828 struct ANASTASIS_Challenge *); 829 r->cs 830 = GNUNET_new_array (r->ri.cs_len, 831 struct ANASTASIS_Challenge); 832 for (unsigned int i = 0; i < r->ri.cs_len; i++) 833 { 834 struct ANASTASIS_Challenge *cs = &r->cs[i]; 835 const char *instructions; 836 const char *url; 837 const char *escrow_type; 838 struct GNUNET_JSON_Specification spec[] = { 839 GNUNET_JSON_spec_fixed_auto ("uuid", 840 &cs->ci.uuid), 841 TALER_JSON_spec_web_url ("url", 842 &url), 843 GNUNET_JSON_spec_string ("instructions", 844 &instructions), 845 GNUNET_JSON_spec_fixed_auto ("truth_key", 846 &cs->truth_key), 847 GNUNET_JSON_spec_fixed_auto ("question_salt", 848 &cs->question_salt), 849 GNUNET_JSON_spec_fixed_auto ("provider_salt", 850 &cs->provider_salt), 851 GNUNET_JSON_spec_string ("escrow_type", 852 &escrow_type), 853 GNUNET_JSON_spec_end () 854 }; 855 856 r->ri.cs[i] = cs; 857 cs->recovery = r; 858 if (GNUNET_OK != 859 GNUNET_JSON_parse (json_array_get (esc_methods, 860 i), 861 spec, 862 NULL, NULL)) 863 { 864 GNUNET_break_op (0); 865 r->csc (r->csc_cls, 866 ANASTASIS_RS_POLICY_MALFORMED_JSON, 867 NULL, 868 0); 869 goto cleanup; 870 } 871 cs->url = GNUNET_strdup (url); 872 cs->type = GNUNET_strdup (escrow_type); 873 cs->ci.type = cs->type; 874 cs->ci.provider_url = cs->url; 875 cs->instructions = GNUNET_strdup (instructions); 876 cs->ci.instructions = cs->instructions; 877 } 878 879 for (unsigned int j = 0; j < r->ri.dps_len; j++) 880 { 881 struct DecryptionPolicy *dp = &r->dps[j]; 882 const json_t *uuids; 883 json_t *juuid; 884 size_t n_index; 885 struct GNUNET_JSON_Specification spec[] = { 886 GNUNET_JSON_spec_varsize ("master_key", 887 &dp->emk, 888 &dp->emk_size), 889 GNUNET_JSON_spec_fixed_auto ("master_salt", 890 &dp->master_salt), 891 GNUNET_JSON_spec_array_const ("uuids", 892 &uuids), 893 GNUNET_JSON_spec_end () 894 }; 895 896 r->ri.dps[j] = &r->dps[j].pub_details; 897 if (GNUNET_OK != 898 GNUNET_JSON_parse (json_array_get (dec_policies, 899 j), 900 spec, 901 NULL, NULL)) 902 { 903 GNUNET_break_op (0); 904 r->csc (r->csc_cls, 905 ANASTASIS_RS_POLICY_MALFORMED_JSON, 906 NULL, 907 0); 908 goto cleanup; 909 } 910 911 GNUNET_assert (NULL != dp->emk); 912 GNUNET_assert (dp->emk_size > 0); 913 914 if (json_array_size (uuids) > UINT_MAX) 915 { 916 GNUNET_break_op (0); 917 r->csc (r->csc_cls, 918 ANASTASIS_RS_POLICY_MALFORMED_JSON, 919 NULL, 920 0); 921 goto cleanup; 922 } 923 dp->pub_details.challenges_length 924 = (unsigned int) json_array_size (uuids); 925 dp->pub_details.challenges 926 = GNUNET_new_array (dp->pub_details.challenges_length, 927 struct ANASTASIS_Challenge *); 928 json_array_foreach (uuids, n_index, juuid) 929 { 930 const char *uuid_str = json_string_value (juuid); 931 struct ANASTASIS_CRYPTO_TruthUUIDP uuid; 932 bool found = false; 933 934 if ( (NULL == uuid_str) || 935 (GNUNET_OK != 936 GNUNET_STRINGS_string_to_data ( 937 uuid_str, 938 strlen (uuid_str), 939 &uuid, 940 sizeof (uuid))) ) 941 { 942 GNUNET_break_op (0); 943 r->csc (r->csc_cls, 944 ANASTASIS_RS_POLICY_MALFORMED_JSON, 945 NULL, 946 0); 947 goto cleanup; 948 } 949 for (unsigned int i = 0; i<r->ri.cs_len; i++) 950 { 951 if (0 != 952 GNUNET_memcmp (&uuid, 953 &r->cs[i].ci.uuid)) 954 continue; 955 found = true; 956 dp->pub_details.challenges[n_index] = &r->cs[i]; 957 break; 958 } 959 if (! found) 960 { 961 GNUNET_break_op (0); 962 r->csc (r->csc_cls, 963 ANASTASIS_RS_POLICY_MALFORMED_JSON, 964 NULL, 965 0); 966 goto cleanup; 967 } 968 } 969 } 970 r->pc (r->pc_cls, 971 &r->ri); 972 json_decref (recovery_document); 973 return; 974 cleanup: 975 ANASTASIS_recovery_abort (r); 976 json_decref (recovery_document); 977 } 978 979 980 struct ANASTASIS_Recovery * 981 ANASTASIS_recovery_begin ( 982 struct GNUNET_CURL_Context *ctx, 983 const json_t *id_data, 984 unsigned int version, 985 const char *anastasis_provider_url, 986 const struct ANASTASIS_CRYPTO_ProviderSaltP *provider_salt, 987 ANASTASIS_PolicyCallback pc, 988 void *pc_cls, 989 ANASTASIS_CoreSecretCallback csc, 990 void *csc_cls) 991 { 992 struct ANASTASIS_Recovery *r; 993 struct ANASTASIS_CRYPTO_AccountPublicKeyP pub_key; 994 995 r = GNUNET_new (struct ANASTASIS_Recovery); 996 r->csc = csc; 997 r->csc_cls = csc_cls; 998 r->pc = pc; 999 r->pc_cls = pc_cls; 1000 r->ctx = ctx; 1001 r->id_data = json_incref ((json_t *) id_data); 1002 r->provider_url = GNUNET_strdup (anastasis_provider_url); 1003 ANASTASIS_CRYPTO_user_identifier_derive (id_data, 1004 provider_salt, 1005 &r->id); 1006 ANASTASIS_CRYPTO_account_public_key_derive (&r->id, 1007 &pub_key); 1008 r->ri.version = version; 1009 if (0 != version) 1010 { 1011 r->plo = ANASTASIS_policy_lookup_version (r->ctx, 1012 anastasis_provider_url, 1013 &pub_key, 1014 &policy_lookup_cb, 1015 r, 1016 version); 1017 } 1018 else 1019 { 1020 r->plo = ANASTASIS_policy_lookup (r->ctx, 1021 anastasis_provider_url, 1022 &pub_key, 1023 &policy_lookup_cb, 1024 r); 1025 } 1026 if (NULL == r->plo) 1027 { 1028 GNUNET_break (0); 1029 ANASTASIS_recovery_abort (r); 1030 return NULL; 1031 } 1032 return r; 1033 } 1034 1035 1036 json_t * 1037 ANASTASIS_recovery_serialize (const struct ANASTASIS_Recovery *r) 1038 { 1039 json_t *dps_arr; 1040 json_t *cs_arr; 1041 1042 dps_arr = json_array (); 1043 GNUNET_assert (NULL != dps_arr); 1044 for (unsigned int i = 0; i<r->ri.dps_len; i++) 1045 { 1046 const struct DecryptionPolicy *dp = &r->dps[i]; 1047 json_t *c_arr; 1048 json_t *dps; 1049 1050 c_arr = json_array (); 1051 GNUNET_assert (NULL != c_arr); 1052 for (unsigned int j = 0; j < dp->pub_details.challenges_length; j++) 1053 { 1054 const struct ANASTASIS_Challenge *c = dp->pub_details.challenges[j]; 1055 json_t *cs; 1056 1057 cs = GNUNET_JSON_PACK ( 1058 GNUNET_JSON_pack_data_auto ("uuid", 1059 &c->ci.uuid)); 1060 GNUNET_assert (0 == 1061 json_array_append_new (c_arr, 1062 cs)); 1063 } 1064 GNUNET_assert (NULL != dp->emk); 1065 dps = GNUNET_JSON_PACK ( 1066 GNUNET_JSON_pack_data_varsize ("encrypted_master_key", 1067 dp->emk, 1068 dp->emk_size), 1069 GNUNET_JSON_pack_data_auto ("master_salt", 1070 &dp->master_salt), 1071 GNUNET_JSON_pack_array_steal ("challenges", 1072 c_arr)); 1073 GNUNET_assert (0 == 1074 json_array_append_new (dps_arr, 1075 dps)); 1076 } 1077 cs_arr = json_array (); 1078 GNUNET_assert (NULL != cs_arr); 1079 for (unsigned int i = 0; i<r->ri.cs_len; i++) 1080 { 1081 const struct ANASTASIS_Challenge *c = &r->cs[i]; 1082 json_t *cs; 1083 1084 cs = GNUNET_JSON_PACK ( 1085 GNUNET_JSON_pack_data_auto ("uuid", 1086 &c->ci.uuid), 1087 GNUNET_JSON_pack_string ("uuid-display", 1088 ANASTASIS_CRYPTO_uuid2s (&c->ci.uuid)), 1089 GNUNET_JSON_pack_data_auto ("truth_key", 1090 &c->truth_key), 1091 GNUNET_JSON_pack_data_auto ("question_salt", 1092 &c->question_salt), 1093 GNUNET_JSON_pack_data_auto ("provider_salt", 1094 &c->provider_salt), 1095 GNUNET_JSON_pack_allow_null ( 1096 GNUNET_JSON_pack_data_varsize ("key_share", 1097 c->ci.solved 1098 ? &c->key_share 1099 : NULL, 1100 sizeof (c->key_share))), 1101 GNUNET_JSON_pack_string ("url", 1102 c->url), 1103 GNUNET_JSON_pack_string ("type", 1104 c->type), 1105 GNUNET_JSON_pack_string ("instructions", 1106 c->instructions), 1107 GNUNET_JSON_pack_bool ("solved", 1108 c->ci.solved), 1109 GNUNET_JSON_pack_bool ("async", 1110 c->ci.async)); 1111 GNUNET_assert (0 == 1112 json_array_append_new (cs_arr, 1113 cs)); 1114 } 1115 1116 return GNUNET_JSON_PACK ( 1117 GNUNET_JSON_pack_data_auto ("id", 1118 &r->id), 1119 GNUNET_JSON_pack_array_steal ("decryption_policies", 1120 dps_arr), 1121 GNUNET_JSON_pack_array_steal ("challenges", 1122 cs_arr), 1123 GNUNET_JSON_pack_uint64 ("version", 1124 r->ri.version), 1125 GNUNET_JSON_pack_object_incref ("id_data", 1126 (json_t *) r->id_data), 1127 GNUNET_JSON_pack_string ("provider_url", 1128 r->provider_url), 1129 GNUNET_JSON_pack_allow_null ( 1130 GNUNET_JSON_pack_string ("secret_name", 1131 r->secret_name)), 1132 GNUNET_JSON_pack_data_varsize ("encrypted_core_secret", 1133 r->enc_core_secret, 1134 r->enc_core_secret_size)); 1135 } 1136 1137 1138 /** 1139 * Parse the @a cs_array with information about 1140 * the various challenges and their solution state 1141 * and update @a r accordingly 1142 * 1143 * @param[in,out] r recovery information to update 1144 * @param cs_arr serialized data to parse 1145 * @return #GNUNET_OK on success 1146 */ 1147 static enum GNUNET_GenericReturnValue 1148 parse_cs_array (struct ANASTASIS_Recovery *r, 1149 const json_t *cs_arr) 1150 { 1151 json_t *cs; 1152 size_t n_index; 1153 1154 if (! json_is_array (cs_arr)) 1155 { 1156 GNUNET_break_op (0); 1157 return GNUNET_SYSERR; 1158 } 1159 if (json_array_size (cs_arr) > UINT_MAX) 1160 { 1161 GNUNET_break_op (0); 1162 return GNUNET_SYSERR; 1163 } 1164 r->ri.cs_len 1165 = (unsigned int) json_array_size (cs_arr); 1166 r->solved_challenges 1167 = GNUNET_new_array (r->ri.cs_len, 1168 struct ANASTASIS_Challenge *); 1169 r->ri.cs = GNUNET_new_array (r->ri.cs_len, 1170 struct ANASTASIS_Challenge *); 1171 r->cs = GNUNET_new_array (r->ri.cs_len, 1172 struct ANASTASIS_Challenge); 1173 json_array_foreach (cs_arr, n_index, cs) 1174 { 1175 struct ANASTASIS_Challenge *c = &r->cs[n_index]; 1176 const char *instructions; 1177 const char *url; 1178 const char *escrow_type; 1179 bool no_key_share; 1180 struct GNUNET_JSON_Specification spec[] = { 1181 GNUNET_JSON_spec_fixed_auto ("uuid", 1182 &c->ci.uuid), 1183 TALER_JSON_spec_web_url ("url", 1184 &url), 1185 GNUNET_JSON_spec_string ("instructions", 1186 &instructions), 1187 GNUNET_JSON_spec_fixed_auto ("truth_key", 1188 &c->truth_key), 1189 GNUNET_JSON_spec_fixed_auto ("question_salt", 1190 &c->question_salt), 1191 GNUNET_JSON_spec_fixed_auto ("provider_salt", 1192 &c->provider_salt), 1193 GNUNET_JSON_spec_string ("type", 1194 &escrow_type), 1195 GNUNET_JSON_spec_mark_optional ( 1196 GNUNET_JSON_spec_bool ("async", 1197 &c->ci.async), 1198 NULL), 1199 GNUNET_JSON_spec_mark_optional ( 1200 GNUNET_JSON_spec_fixed_auto ("key_share", 1201 &c->key_share), 1202 &no_key_share), 1203 GNUNET_JSON_spec_end () 1204 }; 1205 1206 r->ri.cs[n_index] = c; 1207 c->recovery = r; 1208 if (GNUNET_OK != 1209 GNUNET_JSON_parse (cs, 1210 spec, 1211 NULL, NULL)) 1212 { 1213 GNUNET_break_op (0); 1214 return GNUNET_SYSERR; 1215 } 1216 c->url = GNUNET_strdup (url); 1217 c->type = GNUNET_strdup (escrow_type); 1218 c->ci.type = c->type; 1219 c->instructions = GNUNET_strdup (instructions); 1220 c->ci.instructions = c->instructions; 1221 c->ci.provider_url = c->url; 1222 if (! no_key_share) 1223 { 1224 c->ci.solved = true; 1225 r->solved_challenges[r->solved_challenge_pos++] = c; 1226 } 1227 } 1228 return GNUNET_OK; 1229 } 1230 1231 1232 /** 1233 * Parse the @a dps_array with our decryption policies 1234 * and update @a r accordingly 1235 * 1236 * @param[in,out] r recovery information to update 1237 * @param dps_arr serialized data to parse 1238 * @return #GNUNET_OK on success 1239 */ 1240 static enum GNUNET_GenericReturnValue 1241 parse_dps_array (struct ANASTASIS_Recovery *r, 1242 const json_t *dps_arr) 1243 { 1244 json_t *dps; 1245 size_t n_index; 1246 1247 if (! json_is_array (dps_arr)) 1248 { 1249 GNUNET_break_op (0); 1250 return GNUNET_SYSERR; 1251 } 1252 if (json_array_size (dps_arr) > UINT_MAX) 1253 { 1254 GNUNET_break_op (0); 1255 return GNUNET_SYSERR; 1256 } 1257 r->ri.dps_len 1258 = (unsigned int) json_array_size (dps_arr); 1259 r->dps = GNUNET_new_array (r->ri.dps_len, 1260 struct DecryptionPolicy); 1261 r->ri.dps = GNUNET_new_array (r->ri.dps_len, 1262 struct ANASTASIS_DecryptionPolicy *); 1263 1264 json_array_foreach (dps_arr, n_index, dps) 1265 { 1266 struct DecryptionPolicy *dp = &r->dps[n_index]; 1267 const json_t *challenges; 1268 struct GNUNET_JSON_Specification spec[] = { 1269 GNUNET_JSON_spec_varsize ("encrypted_master_key", 1270 &dp->emk, 1271 &dp->emk_size), 1272 GNUNET_JSON_spec_fixed_auto ("master_salt", 1273 &dp->master_salt), 1274 GNUNET_JSON_spec_array_const ("challenges", 1275 &challenges), 1276 GNUNET_JSON_spec_end () 1277 }; 1278 const char *err_json_name; 1279 unsigned int err_line; 1280 1281 r->ri.dps[n_index] = &dp->pub_details; 1282 if (GNUNET_OK != 1283 GNUNET_JSON_parse (dps, 1284 spec, 1285 &err_json_name, 1286 &err_line)) 1287 { 1288 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1289 "Failed to parse decryption policy JSON entry `%s'\n", 1290 err_json_name); 1291 json_dumpf (dps, 1292 stderr, 1293 JSON_INDENT (2)); 1294 return GNUNET_SYSERR; 1295 } 1296 GNUNET_assert (NULL != dp->emk); 1297 GNUNET_assert (dp->emk_size > 0); 1298 if (json_array_size (challenges) > UINT_MAX) 1299 { 1300 GNUNET_break_op (0); 1301 return GNUNET_SYSERR; 1302 } 1303 dp->pub_details.challenges_length 1304 = (unsigned int) json_array_size (challenges); 1305 dp->pub_details.challenges 1306 = GNUNET_new_array (dp->pub_details.challenges_length, 1307 struct ANASTASIS_Challenge *); 1308 1309 { 1310 json_t *challenge; 1311 size_t c_index; 1312 json_array_foreach (challenges, c_index, challenge) 1313 { 1314 struct ANASTASIS_CRYPTO_TruthUUIDP uuid; 1315 struct GNUNET_JSON_Specification ispec[] = { 1316 GNUNET_JSON_spec_fixed_auto ("uuid", 1317 &uuid), 1318 GNUNET_JSON_spec_end () 1319 }; 1320 bool found = false; 1321 1322 if (GNUNET_OK != 1323 GNUNET_JSON_parse (challenge, 1324 ispec, 1325 NULL, NULL)) 1326 { 1327 GNUNET_break_op (0); 1328 GNUNET_JSON_parse_free (spec); 1329 return GNUNET_SYSERR; 1330 } 1331 for (unsigned int i = 0; i<r->ri.cs_len; i++) 1332 { 1333 if (0 != 1334 GNUNET_memcmp (&uuid, 1335 &r->cs[i].ci.uuid)) 1336 continue; 1337 dp->pub_details.challenges[c_index] = &r->cs[i]; 1338 found = true; 1339 } 1340 if (! found) 1341 { 1342 GNUNET_break_op (0); 1343 GNUNET_JSON_parse_free (spec); 1344 return GNUNET_SYSERR; 1345 } 1346 } 1347 } 1348 /* Do NOT free the spec: we are still using dp->ems. */ 1349 } 1350 return GNUNET_OK; 1351 } 1352 1353 1354 /** 1355 * Asynchronously call "pc" on the recovery information. 1356 * 1357 * @param cls a `struct ANASTASIS_Recovery *` 1358 */ 1359 static void 1360 run_async_pc (void *cls) 1361 { 1362 struct ANASTASIS_Recovery *r = cls; 1363 1364 r->do_async = NULL; 1365 r->pc (r->pc_cls, 1366 &r->ri); 1367 } 1368 1369 1370 struct ANASTASIS_Recovery * 1371 ANASTASIS_recovery_deserialize (struct GNUNET_CURL_Context *ctx, 1372 const json_t *input, 1373 ANASTASIS_PolicyCallback pc, 1374 void *pc_cls, 1375 ANASTASIS_CoreSecretCallback csc, 1376 void *csc_cls) 1377 { 1378 struct ANASTASIS_Recovery *r; 1379 1380 r = GNUNET_new (struct ANASTASIS_Recovery); 1381 r->csc = csc; 1382 r->csc_cls = csc_cls; 1383 r->pc = pc; 1384 r->pc_cls = pc_cls; 1385 r->ctx = ctx; 1386 { 1387 const char *err_json_name; 1388 unsigned int err_line; 1389 uint32_t version; 1390 const json_t *dps_arr; 1391 const json_t *cs_arr; 1392 const json_t *id_data; 1393 const char *provider_url; 1394 const char *secret_name; 1395 void *ecs; 1396 size_t ecs_size; 1397 struct GNUNET_JSON_Specification spec[] = { 1398 GNUNET_JSON_spec_fixed_auto ("id", 1399 &r->id), 1400 TALER_JSON_spec_web_url ("provider_url", 1401 &provider_url), 1402 GNUNET_JSON_spec_mark_optional ( 1403 GNUNET_JSON_spec_string ("secret_name", 1404 &secret_name), 1405 NULL), 1406 GNUNET_JSON_spec_uint32 ("version", 1407 &version), 1408 GNUNET_JSON_spec_array_const ("decryption_policies", 1409 &dps_arr), 1410 GNUNET_JSON_spec_array_const ("challenges", 1411 &cs_arr), 1412 GNUNET_JSON_spec_object_const ("id_data", 1413 &id_data), 1414 GNUNET_JSON_spec_varsize ("encrypted_core_secret", 1415 &ecs, 1416 &ecs_size), 1417 GNUNET_JSON_spec_end () 1418 }; 1419 1420 if (GNUNET_OK != 1421 GNUNET_JSON_parse (input, 1422 spec, 1423 &err_json_name, 1424 &err_line)) 1425 { 1426 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, 1427 "Failed to parse recovery document JSON entry `%s'\n", 1428 err_json_name); 1429 json_dumpf (input, 1430 stderr, 1431 JSON_INDENT (2)); 1432 return NULL; 1433 } 1434 r->ri.version = version; 1435 if ( (GNUNET_OK != 1436 parse_cs_array (r, 1437 cs_arr)) || 1438 (GNUNET_OK != 1439 parse_dps_array (r, 1440 dps_arr)) ) 1441 { 1442 GNUNET_break_op (0); 1443 ANASTASIS_recovery_abort (r); 1444 GNUNET_JSON_parse_free (spec); 1445 return NULL; 1446 } 1447 r->id_data = json_incref ((json_t *) id_data); 1448 r->provider_url = GNUNET_strdup (provider_url); 1449 if (NULL != secret_name) 1450 r->secret_name = GNUNET_strdup (secret_name); 1451 r->ri.secret_name = r->secret_name; 1452 if (0 != ecs_size) 1453 { 1454 r->enc_core_secret = GNUNET_memdup (ecs, 1455 ecs_size); 1456 r->enc_core_secret_size = ecs_size; 1457 } 1458 GNUNET_JSON_parse_free (spec); 1459 } 1460 if (0 == r->ri.dps_len) 1461 { 1462 struct ANASTASIS_CRYPTO_AccountPublicKeyP pub_key; 1463 1464 ANASTASIS_CRYPTO_account_public_key_derive (&r->id, 1465 &pub_key); 1466 if (0 != r->ri.version) 1467 { 1468 r->plo = ANASTASIS_policy_lookup_version (r->ctx, 1469 r->provider_url, 1470 &pub_key, 1471 &policy_lookup_cb, 1472 r, 1473 r->ri.version); 1474 } 1475 else 1476 { 1477 r->plo = ANASTASIS_policy_lookup (r->ctx, 1478 r->provider_url, 1479 &pub_key, 1480 &policy_lookup_cb, 1481 r); 1482 } 1483 if (NULL == r->plo) 1484 { 1485 GNUNET_break (0); 1486 ANASTASIS_recovery_abort (r); 1487 return NULL; 1488 } 1489 } 1490 else 1491 { 1492 r->do_async = GNUNET_SCHEDULER_add_now (&run_async_pc, 1493 r); 1494 } 1495 return r; 1496 } 1497 1498 1499 void 1500 ANASTASIS_recovery_abort (struct ANASTASIS_Recovery *r) 1501 { 1502 if (NULL != r->do_async) 1503 { 1504 GNUNET_SCHEDULER_cancel (r->do_async); 1505 r->do_async = NULL; 1506 } 1507 if (NULL != r->plo) 1508 { 1509 ANASTASIS_policy_lookup_cancel (r->plo); 1510 r->plo = NULL; 1511 } 1512 GNUNET_free (r->solved_challenges); 1513 for (unsigned int j = 0; j < r->ri.dps_len; j++) 1514 { 1515 GNUNET_free (r->dps[j].pub_details.challenges); 1516 GNUNET_free (r->dps[j].emk); 1517 } 1518 GNUNET_free (r->ri.dps); 1519 for (unsigned int i = 0; i < r->ri.cs_len; i++) 1520 { 1521 struct ANASTASIS_Challenge *cs = &r->cs[i]; 1522 1523 if (NULL != cs->tso) 1524 { 1525 ANASTASIS_truth_solve_cancel (cs->tso); 1526 cs->tso = NULL; 1527 } 1528 GNUNET_free (cs->url); 1529 GNUNET_free (cs->type); 1530 GNUNET_free (cs->instructions); 1531 GNUNET_free (cs->answer); 1532 } 1533 GNUNET_free (r->ri.cs); 1534 GNUNET_free (r->cs); 1535 GNUNET_free (r->dps); 1536 json_decref (r->id_data); 1537 GNUNET_free (r->provider_url); 1538 GNUNET_free (r->secret_name); 1539 GNUNET_free (r->enc_core_secret); 1540 GNUNET_free (r); 1541 }